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 46 ScrollbarTheme* ScrollbarTheme::nativeTheme() 47 { 48 static ScrollbarThemeWx theme; 49 return &theme; 50 } 51 52 ScrollbarThemeWx::~ScrollbarThemeWx() 53 { 54 } 55 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 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 74 int ScrollbarThemeWx::minimumThumbLength(Scrollbar* scrollbar) 75 { 76 return 20; 77 } 78 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 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 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 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 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 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 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