06a653364a5b2ddd93b3b2b3d3915633c89c9c68
[WebKit-https.git] / WebCore / platform / win / ScrollbarThemeSafari.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 "ScrollbarThemeSafari.h"
28
29 #if USE(SAFARI_THEME)
30
31 #include "GraphicsContext.h"
32 #include "IntRect.h"
33 #include "Page.h"
34 #include "PlatformMouseEvent.h"
35 #include "Scrollbar.h"
36 #include "ScrollbarClient.h"
37 #include "ScrollbarThemeWin.h"
38 #include "Settings.h"
39 #include "SoftLinking.h"
40
41 #include <CoreGraphics/CoreGraphics.h>
42
43 // If you have an empty placeholder SafariThemeConstants.h, then include SafariTheme.h
44 // This is a workaround until a version of WebKitSupportLibrary is released with an updated SafariThemeConstants.h 
45 #include <SafariTheme/SafariThemeConstants.h>
46 #ifndef SafariThemeConstants_h
47 #include <SafariTheme/SafariTheme.h>
48 #endif
49
50 // FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow.
51
52 using namespace std;
53
54 namespace WebCore {
55
56 using namespace SafariTheme;
57
58 ScrollbarTheme* ScrollbarTheme::nativeTheme()
59 {
60     static ScrollbarThemeSafari safariTheme;
61     static ScrollbarThemeWin windowsTheme;
62     if (Settings::shouldPaintNativeControls())
63         return &windowsTheme;
64     return &safariTheme;
65 }
66
67 // FIXME: Get these numbers from CoreUI.
68 static int cScrollbarThickness[] = { 15, 11 };
69 static int cRealButtonLength[] = { 28, 21 };
70 static int cButtonInset[] = { 14, 11 };
71 static int cButtonHitInset[] = { 3, 2 };
72 // cRealButtonLength - cButtonInset
73 static int cButtonLength[] = { 14, 10 };
74 static int cThumbMinLength[] = { 26, 20 };
75
76 #if !defined(NDEBUG) && defined(USE_DEBUG_SAFARI_THEME)
77 SOFT_LINK_DEBUG_LIBRARY(SafariTheme)
78 #else
79 SOFT_LINK_LIBRARY(SafariTheme)
80 #endif
81
82 SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, 
83             (ThemePart part, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state),
84             (part, context, rect, size, state))
85
86 static ScrollbarControlState scrollbarControlStateFromThemeState(ThemeControlState state)
87 {
88     ScrollbarControlState s = 0;
89     if (state & ActiveState)
90         s |= ActiveScrollbarState;
91     if (state & EnabledState)
92         s |= EnabledScrollbarState;
93     if (state & PressedState)
94         s |= PressedScrollbarState;
95     return s;
96 }
97
98 ScrollbarThemeSafari::~ScrollbarThemeSafari()
99 {
100 }
101
102 int ScrollbarThemeSafari::scrollbarThickness(ScrollbarControlSize controlSize)
103 {
104     return cScrollbarThickness[controlSize];
105 }
106
107 bool ScrollbarThemeSafari::hasButtons(Scrollbar* scrollbar)
108 {
109     return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ? 
110              scrollbar->width() : 
111              scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]);
112 }
113
114 bool ScrollbarThemeSafari::hasThumb(Scrollbar* scrollbar)
115 {
116     return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ? 
117              scrollbar->width() : 
118              scrollbar->height()) >= 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1;
119 }
120
121 static IntRect buttonRepaintRect(const IntRect& buttonRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, bool start)
122 {
123     IntRect paintRect(buttonRect);
124     if (orientation == HorizontalScrollbar) {
125         paintRect.setWidth(cRealButtonLength[controlSize]);
126         if (!start)
127             paintRect.setX(buttonRect.x() - (cRealButtonLength[controlSize] - buttonRect.width()));
128     } else {
129         paintRect.setHeight(cRealButtonLength[controlSize]);
130         if (!start)
131             paintRect.setY(buttonRect.y() - (cRealButtonLength[controlSize] - buttonRect.height()));
132     }
133
134     return paintRect;
135 }
136
137 IntRect ScrollbarThemeSafari::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting)
138 {
139     IntRect result;
140
141     // Windows just has single arrows.
142     if (part == BackButtonEndPart)
143         return result;
144
145     int thickness = scrollbarThickness(scrollbar->controlSize());
146     if (scrollbar->orientation() == HorizontalScrollbar)
147         result = IntRect(scrollbar->x(), scrollbar->y(), cButtonLength[scrollbar->controlSize()], thickness);
148     else
149         result = IntRect(scrollbar->x(), scrollbar->y(), thickness, cButtonLength[scrollbar->controlSize()]);
150     if (painting)
151         return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), true);
152     return result;
153 }
154
155 IntRect ScrollbarThemeSafari::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting)
156 {
157     IntRect result;
158     
159     // Windows just has single arrows.
160     if (part == ForwardButtonStartPart)
161         return result;
162
163     int thickness = scrollbarThickness(scrollbar->controlSize());
164     if (scrollbar->orientation() == HorizontalScrollbar)
165         result = IntRect(scrollbar->x() + scrollbar->width() - cButtonLength[scrollbar->controlSize()], scrollbar->y(), cButtonLength[scrollbar->controlSize()], thickness);
166     else
167         result = IntRect(scrollbar->x(), scrollbar->y() + scrollbar->height() - cButtonLength[scrollbar->controlSize()], thickness, cButtonLength[scrollbar->controlSize()]);
168     if (painting)
169         return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), false);
170     return result;
171 }
172
173 static IntRect trackRepaintRect(const IntRect& trackRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
174 {
175     IntRect paintRect(trackRect);
176     if (orientation == HorizontalScrollbar)
177         paintRect.inflateX(cButtonLength[controlSize]);
178     else
179         paintRect.inflateY(cButtonLength[controlSize]);
180
181     return paintRect;
182 }
183
184 IntRect ScrollbarThemeSafari::trackRect(Scrollbar* scrollbar, bool painting)
185 {
186     if (painting || !hasButtons(scrollbar))
187         return scrollbar->frameRect();
188     
189     IntRect result;
190     int thickness = scrollbarThickness(scrollbar->controlSize());
191     if (scrollbar->orientation() == HorizontalScrollbar) 
192         return IntRect(scrollbar->x() + cButtonLength[scrollbar->controlSize()], scrollbar->y(), scrollbar->width() - 2 * cButtonLength[scrollbar->controlSize()], thickness);
193     return IntRect(scrollbar->x(), scrollbar->y() + cButtonLength[scrollbar->controlSize()], thickness, scrollbar->height() - 2 * cButtonLength[scrollbar->controlSize()]);
194 }
195
196 int ScrollbarThemeSafari::minimumThumbLength(Scrollbar* scrollbar)
197 {
198     return cThumbMinLength[scrollbar->controlSize()];
199 }
200
201 bool ScrollbarThemeSafari::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
202 {
203     return evt.shiftKey() && evt.button() == LeftButton;
204 }
205
206 void ScrollbarThemeSafari::paintTrackBackground(GraphicsContext* graphicsContext, Scrollbar* scrollbar, const IntRect& trackRect)
207 {
208     if (!SafariThemeLibrary())
209         return;
210     NSControlSize size = scrollbar->controlSize() == SmallScrollbar ? NSSmallControlSize : NSRegularControlSize;
211     ThemeControlState state = 0;
212     if (scrollbar->client()->isActive())
213         state |= ActiveState;
214     if (hasButtons(scrollbar))
215         state |= EnabledState;
216     paintThemePart(scrollbar->orientation() == VerticalScrollbar ? VScrollTrackPart : HScrollTrackPart, graphicsContext->platformContext(), trackRect, size, state); 
217 }
218
219 void ScrollbarThemeSafari::paintButton(GraphicsContext* graphicsContext, Scrollbar* scrollbar, const IntRect& buttonRect, ScrollbarPart part)
220 {
221     if (!SafariThemeLibrary())
222         return;
223     NSControlSize size = scrollbar->controlSize() == SmallScrollbar ? NSSmallControlSize : NSRegularControlSize;
224     ThemeControlState state = 0;
225     if (scrollbar->client()->isActive())
226         state |= ActiveState;
227     if (hasButtons(scrollbar))
228         state |= EnabledState;
229     if (scrollbar->pressedPart() == part)
230         state |= PressedState;
231     if (part == BackButtonStartPart)
232         paintThemePart(scrollbar->orientation() == VerticalScrollbar ? ScrollUpArrowPart : ScrollLeftArrowPart, graphicsContext->platformContext(),
233                        buttonRect, size, state);
234     else if (part == ForwardButtonEndPart)
235         paintThemePart(scrollbar->orientation() == VerticalScrollbar ? ScrollDownArrowPart : ScrollRightArrowPart, graphicsContext->platformContext(),
236                        buttonRect, size, state);
237 }
238
239 void ScrollbarThemeSafari::paintThumb(GraphicsContext* graphicsContext, Scrollbar* scrollbar, const IntRect& thumbRect)
240 {
241     if (!SafariThemeLibrary())
242         return;
243     NSControlSize size = scrollbar->controlSize() == SmallScrollbar ? NSSmallControlSize : NSRegularControlSize;
244     ThemeControlState state = 0;
245     if (scrollbar->client()->isActive())
246         state |= ActiveState;
247     if (hasThumb(scrollbar))
248         state |= EnabledState;
249     if (scrollbar->pressedPart() == ThumbPart)
250         state |= PressedState;
251     paintThemePart(scrollbar->orientation() == VerticalScrollbar ? VScrollThumbPart : HScrollThumbPart, graphicsContext->platformContext(), 
252                    thumbRect, size, state);
253 }
254
255 }
256
257 #endif