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 
34 using namespace std;
35 
36 namespace WebCore {
37 
RenderScrollbarPart(Node * node,RenderScrollbar * scrollbar,ScrollbarPart part)38 RenderScrollbarPart::RenderScrollbarPart(Node* node, RenderScrollbar* scrollbar, ScrollbarPart part)
39     : RenderBlock(node)
40     , m_scrollbar(scrollbar)
41     , m_part(part)
42 {
43 }
44 
~RenderScrollbarPart()45 RenderScrollbarPart::~RenderScrollbarPart()
46 {
47 }
48 
layout()49 void RenderScrollbarPart::layout()
50 {
51     setLocation(IntPoint()); // We don't worry about positioning ourselves.  We're just determining our minimum width/height.
52     if (m_scrollbar->orientation() == HorizontalScrollbar)
53         layoutHorizontalPart();
54     else
55         layoutVerticalPart();
56 
57     setNeedsLayout(false);
58 }
59 
layoutHorizontalPart()60 void RenderScrollbarPart::layoutHorizontalPart()
61 {
62     if (m_part == ScrollbarBGPart) {
63         setWidth(m_scrollbar->width());
64         computeScrollbarHeight();
65     } else {
66         computeScrollbarWidth();
67         setHeight(m_scrollbar->height());
68     }
69 }
70 
layoutVerticalPart()71 void RenderScrollbarPart::layoutVerticalPart()
72 {
73     if (m_part == ScrollbarBGPart) {
74         computeScrollbarWidth();
75         setHeight(m_scrollbar->height());
76     } else {
77         setWidth(m_scrollbar->width());
78         computeScrollbarHeight();
79     }
80 }
81 
calcScrollbarThicknessUsing(const Length & l,int containingLength)82 static int calcScrollbarThicknessUsing(const Length& l, int containingLength)
83 {
84     if (l.isIntrinsicOrAuto())
85         return ScrollbarTheme::nativeTheme()->scrollbarThickness();
86     return l.calcMinValue(containingLength);
87 }
88 
computeScrollbarWidth()89 void RenderScrollbarPart::computeScrollbarWidth()
90 {
91     if (!m_scrollbar->owningRenderer())
92         return;
93     int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->borderLeft() - m_scrollbar->owningRenderer()->borderRight();
94     int w = calcScrollbarThicknessUsing(style()->width(), visibleSize);
95     int minWidth = calcScrollbarThicknessUsing(style()->minWidth(), visibleSize);
96     int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(style()->maxWidth(), visibleSize);
97     setWidth(max(minWidth, min(maxWidth, w)));
98 
99     // Buttons and track pieces can all have margins along the axis of the scrollbar.
100     m_marginLeft = style()->marginLeft().calcMinValue(visibleSize);
101     m_marginRight = style()->marginRight().calcMinValue(visibleSize);
102 }
103 
computeScrollbarHeight()104 void RenderScrollbarPart::computeScrollbarHeight()
105 {
106     if (!m_scrollbar->owningRenderer())
107         return;
108     int visibleSize = m_scrollbar->owningRenderer()->height() -  m_scrollbar->owningRenderer()->borderTop() - m_scrollbar->owningRenderer()->borderBottom();
109     int h = calcScrollbarThicknessUsing(style()->height(), visibleSize);
110     int minHeight = calcScrollbarThicknessUsing(style()->minHeight(), visibleSize);
111     int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(style()->maxHeight(), visibleSize);
112     setHeight(max(minHeight, min(maxHeight, h)));
113 
114     // Buttons and track pieces can all have margins along the axis of the scrollbar.
115     m_marginTop = style()->marginTop().calcMinValue(visibleSize);
116     m_marginBottom = style()->marginBottom().calcMinValue(visibleSize);
117 }
118 
computePreferredLogicalWidths()119 void RenderScrollbarPart::computePreferredLogicalWidths()
120 {
121     if (!preferredLogicalWidthsDirty())
122         return;
123 
124     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
125 
126     setPreferredLogicalWidthsDirty(false);
127 }
128 
styleWillChange(StyleDifference diff,const RenderStyle * newStyle)129 void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
130 {
131     RenderBlock::styleWillChange(diff, newStyle);
132     setInline(false);
133 }
134 
styleDidChange(StyleDifference diff,const RenderStyle * oldStyle)135 void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
136 {
137     RenderBlock::styleDidChange(diff, oldStyle);
138     setInline(false);
139     setPositioned(false);
140     setFloating(false);
141     setHasOverflowClip(false);
142     if (oldStyle && m_scrollbar && m_part != NoPart && diff >= StyleDifferenceRepaint)
143         m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
144 }
145 
imageChanged(WrappedImagePtr image,const IntRect * rect)146 void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rect)
147 {
148     if (m_scrollbar && m_part != NoPart)
149         m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
150     else {
151         if (FrameView* frameView = view()->frameView()) {
152             if (frameView->isFrameViewScrollCorner(this)) {
153                 frameView->invalidateScrollCorner();
154                 return;
155             }
156         }
157 
158         RenderBlock::imageChanged(image, rect);
159     }
160 }
161 
paintIntoRect(GraphicsContext * graphicsContext,int tx,int ty,const IntRect & rect)162 void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, int tx, int ty, const IntRect& rect)
163 {
164     // Make sure our dimensions match the rect.
165     setLocation(rect.x() - tx, rect.y() - ty);
166     setWidth(rect.width());
167     setHeight(rect.height());
168 
169     if (graphicsContext->paintingDisabled())
170         return;
171 
172     // Now do the paint.
173     PaintInfo paintInfo(graphicsContext, rect, PaintPhaseBlockBackground, false, 0, 0);
174     paint(paintInfo, tx, ty);
175     paintInfo.phase = PaintPhaseChildBlockBackgrounds;
176     paint(paintInfo, tx, ty);
177     paintInfo.phase = PaintPhaseFloat;
178     paint(paintInfo, tx, ty);
179     paintInfo.phase = PaintPhaseForeground;
180     paint(paintInfo, tx, ty);
181     paintInfo.phase = PaintPhaseOutline;
182     paint(paintInfo, tx, ty);
183 }
184 
185 }
186