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 "ScrollbarThemeWx.h"
28
29 #include "HostWindow.h"
30 #include "NotImplemented.h"
31 #include "PlatformMouseEvent.h"
32 #include "ScrollableArea.h"
33 #include "Scrollbar.h"
34 #include "scrollbar_render.h"
35 #include "ScrollbarThemeComposite.h"
36 #include "ScrollView.h"
37
38 #include <wx/defs.h>
39 #include <wx/dcgraph.h>
40 #include <wx/settings.h>
41
42 const int cMacButtonOverlap = 4;
43
44 namespace WebCore {
45
nativeTheme()46 ScrollbarTheme* ScrollbarTheme::nativeTheme()
47 {
48 static ScrollbarThemeWx theme;
49 return &theme;
50 }
51
~ScrollbarThemeWx()52 ScrollbarThemeWx::~ScrollbarThemeWx()
53 {
54 }
55
scrollbarThickness(ScrollbarControlSize size)56 int ScrollbarThemeWx::scrollbarThickness(ScrollbarControlSize size)
57 {
58 int thickness = wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
59
60 // fallback for when a platform doesn't define this metric
61 if (thickness <= 0)
62 thickness = 20;
63
64 return thickness;
65 }
66
hasThumb(Scrollbar * scrollbar)67 bool ScrollbarThemeWx::hasThumb(Scrollbar* scrollbar)
68 {
69 // This method is just called as a paint-time optimization to see if
70 // painting the thumb can be skipped. We don't have to be exact here.
71 return thumbLength(scrollbar) > 0;
72 }
73
minimumThumbLength(Scrollbar * scrollbar)74 int ScrollbarThemeWx::minimumThumbLength(Scrollbar* scrollbar)
75 {
76 return 20;
77 }
78
buttonSize(Scrollbar *)79 IntSize ScrollbarThemeWx::buttonSize(Scrollbar*)
80 {
81 #ifdef __WXMAC__
82 return IntSize(20,20);
83 #else
84 return IntSize(16,16);
85 #endif
86 }
87
splitTrack(Scrollbar * scrollbar,const IntRect & unconstrainedTrackRect,IntRect & beforeThumbRect,IntRect & thumbRect,IntRect & afterThumbRect)88 void ScrollbarThemeWx::splitTrack(Scrollbar* scrollbar, const IntRect& unconstrainedTrackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect)
89 {
90 ScrollbarThemeComposite::splitTrack(scrollbar, unconstrainedTrackRect, beforeThumbRect, thumbRect, afterThumbRect);
91 #ifdef __WXMAC__
92 // on Mac, there are a few pixels drawn above the actual track and so adjust
93 // the hit testing rects accordingly
94 int trackStart = 10;
95 if (scrollbar->orientation() == HorizontalScrollbar) {
96 thumbRect.setX(thumbRect.x() + trackStart);
97 afterThumbRect.setX(afterThumbRect.x() - trackStart);
98 } else {
99 thumbRect.setY(thumbRect.y() + trackStart);
100 afterThumbRect.setY(afterThumbRect.y() - trackStart);
101 }
102 #endif
103 }
104
backButtonRect(Scrollbar * scrollbar,ScrollbarPart part,bool)105 IntRect ScrollbarThemeWx::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
106 {
107 // FIXME: Handling this case is needed when there are two sets of arrow buttons
108 // on Mac, one at the top and one at the bottom.
109 if (part == BackButtonEndPart)
110 return IntRect();
111
112 IntSize size = buttonSize(scrollbar);
113 int x = scrollbar->x();
114 int y = scrollbar->y();
115
116 #if __WXMAC__
117 if (scrollbar->orientation() == HorizontalScrollbar)
118 x += scrollbar->width() - (size.width() * 2) + cMacButtonOverlap;
119 else
120 y += scrollbar->height() - (size.height() * 2) + cMacButtonOverlap;
121 #endif
122
123 return IntRect(x, y, size.width(), size.height());
124 }
125
forwardButtonRect(Scrollbar * scrollbar,ScrollbarPart part,bool)126 IntRect ScrollbarThemeWx::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
127 {
128 // FIXME: Handling this case is needed when there are two sets of arrow buttons
129 // on Mac, one at the top and one at the bottom.
130 if (part == ForwardButtonStartPart)
131 return IntRect();
132
133 IntSize size = buttonSize(scrollbar);
134 int x, y;
135 if (scrollbar->orientation() == HorizontalScrollbar) {
136 #ifdef __WXMAC__
137 size.setWidth(size.width() + cMacButtonOverlap);
138 #endif
139 x = scrollbar->x() + scrollbar->width() - size.width();
140 y = scrollbar->y();
141 } else {
142 x = scrollbar->x();
143 #ifdef __WXMAC__
144 size.setHeight(size.height() + cMacButtonOverlap);
145 #endif
146 y = scrollbar->y() + scrollbar->height() - size.height();
147 }
148 return IntRect(x, y, size.width(), size.height());
149 }
150
trackRect(Scrollbar * scrollbar,bool)151 IntRect ScrollbarThemeWx::trackRect(Scrollbar* scrollbar, bool)
152 {
153 IntSize bs = buttonSize(scrollbar);
154 int trackStart = 0;
155 if (scrollbar->orientation() == HorizontalScrollbar)
156 trackStart = bs.width();
157 else
158 trackStart = bs.height();
159
160 #if __WXMAC__
161 trackStart = 0;
162 #endif
163
164 int thickness = scrollbarThickness(scrollbar->controlSize());
165 if (scrollbar->orientation() == HorizontalScrollbar) {
166 if (scrollbar->width() < 2 * thickness)
167 return IntRect();
168 return IntRect(scrollbar->x() + trackStart, scrollbar->y(), scrollbar->width() - 2 * bs.width(), thickness);
169 }
170 if (scrollbar->height() < 2 * thickness)
171 return IntRect();
172 return IntRect(scrollbar->x(), scrollbar->y() + trackStart, thickness, scrollbar->height() - 2 * bs.height());
173 }
174
paintScrollCorner(ScrollView * view,GraphicsContext * context,const IntRect & cornerRect)175 void ScrollbarThemeWx::paintScrollCorner(ScrollView* view, GraphicsContext* context, const IntRect& cornerRect)
176 {
177 // ScrollbarThemeComposite::paintScrollCorner incorrectly assumes that the
178 // ScrollView is a FrameView (see FramelessScrollView), so we cannot let
179 // that code run. For FrameView's this is correct since we don't do custom
180 // scrollbar corner rendering, which ScrollbarThemeComposite supports.
181 ScrollbarTheme::paintScrollCorner(view, context, cornerRect);
182 }
183
paint(Scrollbar * scrollbar,GraphicsContext * context,const IntRect & rect)184 bool ScrollbarThemeWx::paint(Scrollbar* scrollbar, GraphicsContext* context, const IntRect& rect)
185 {
186 wxOrientation orientation = (scrollbar->orientation() == HorizontalScrollbar) ? wxHORIZONTAL : wxVERTICAL;
187 int flags = 0;
188 if (scrollbar->scrollableArea()->isActive())
189 flags |= wxCONTROL_FOCUSED;
190
191 if (!scrollbar->enabled())
192 flags |= wxCONTROL_DISABLED;
193
194 wxDC* dc = static_cast<wxDC*>(context->platformContext());
195
196 context->save();
197 ScrollView* root = scrollbar->root();
198 ASSERT(root);
199 if (!root)
200 return false;
201
202 wxWindow* webview = root->hostWindow()->platformPageClient();
203
204 wxRenderer_DrawScrollbar(webview, *dc, scrollbar->frameRect(), orientation, scrollbar->currentPos(), static_cast<wxScrollbarPart>(scrollbar->pressedPart()),
205 static_cast<wxScrollbarPart>(scrollbar->hoveredPart()), scrollbar->maximum(), scrollbar->pageStep(), flags);
206
207 context->restore();
208 return true;
209 }
210
211 }
212
213