1 /* 2 * Copyright (C) 2009 Kevin Ollivier 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 COMPUTER, 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 COMPUTER, 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 28 #include "scrollbar_render.h" 29 30 #include <wx/defs.h> 31 32 #include <wx/dc.h> 33 #include <wx/dcgraph.h> 34 #include <wx/graphics.h> 35 #include <wx/renderer.h> 36 #include <wx/window.h> 37 38 #include <wx/msw/private.h> 39 #include <wx/msw/uxtheme.h> 40 41 // constants 42 #define SP_BUTTON 1 43 #define SP_THUMBHOR 2 44 #define SP_THUMBVERT 3 45 #define SP_TRACKENDHOR 4 46 #define SP_TRACKENDVERT 7 47 #define SP_GRIPPERHOR 8 48 #define SP_GRIPPERVERT 9 49 50 #define TS_NORMAL 1 51 #define TS_HOVER 2 52 #define TS_ACTIVE 3 53 #define TS_DISABLED 4 54 55 #define TS_UP_BUTTON 0 56 #define TS_DOWN_BUTTON 4 57 #define TS_LEFT_BUTTON 8 58 #define TS_RIGHT_BUTTON 12 59 60 #if wxUSE_GRAPHICS_CONTEXT 61 // TODO remove this dependency (gdiplus needs the macros) 62 // we need to undef because the macros are being defined in WebCorePrefix.h 63 // but GdiPlus.h is not accepting them 64 #undef max 65 #define max(a,b) (((a) > (b)) ? (a) : (b)) 66 67 #undef min 68 #define min(a,b) (((a) < (b)) ? (a) : (b)) 69 70 #include <wx/dcgraph.h> 71 #include "gdiplus.h" 72 using namespace Gdiplus; 73 #endif // wxUSE_GRAPHICS_CONTEXT 74 75 class GraphicsHDC 76 { 77 public: 78 GraphicsHDC(wxDC* dc) 79 { 80 #if wxUSE_GRAPHICS_CONTEXT 81 m_graphics = NULL; 82 wxGCDC* gcdc = wxDynamicCast(dc, wxGCDC); 83 if (gcdc) { 84 m_graphics = (Graphics*)gcdc->GetGraphicsContext()->GetNativeContext(); 85 m_hdc = m_graphics->GetHDC(); 86 } 87 else 88 #endif 89 m_hdc = GetHdcOf(*dc); 90 } 91 92 ~GraphicsHDC() 93 { 94 #if wxUSE_GRAPHICS_CONTEXT 95 if (m_graphics) 96 m_graphics->ReleaseHDC(m_hdc); 97 #endif 98 } 99 100 operator HDC() const { return m_hdc; } 101 102 private: 103 HDC m_hdc; 104 #if wxUSE_GRAPHICS_CONTEXT 105 Graphics* m_graphics; 106 #endif 107 }; 108 109 int getTSStateForPart(wxScrollbarPart part, wxScrollbarPart focusPart, wxScrollbarPart hoverPart, int flags = 0) 110 { 111 int xpState = TS_NORMAL; 112 if (flags & wxCONTROL_DISABLED) 113 xpState = TS_DISABLED; 114 else if (part == focusPart) 115 xpState = TS_ACTIVE; 116 else if (part == hoverPart) 117 xpState = TS_HOVER; 118 119 return xpState; 120 } 121 122 void wxRenderer_DrawScrollbar(wxWindow* window, wxDC& dc, 123 const wxRect& rect, wxOrientation orient, int current, wxScrollbarPart focusPart, wxScrollbarPart hoverPart, int max, int step, int flags) 124 { 125 wxUxThemeEngine *engine = wxUxThemeEngine::Get(); 126 HTHEME hTheme = (HTHEME)engine->OpenThemeData(0, L"SCROLLBAR"); 127 128 bool horiz = orient == wxHORIZONTAL; 129 int part = 0; 130 if (horiz) 131 part = SP_TRACKENDHOR; 132 else 133 part = SP_TRACKENDVERT; 134 135 int xpState = TS_NORMAL; 136 wxRect transRect = rect; 137 138 #if USE(WXGC) 139 // when going from GdiPlus -> Gdi, any GdiPlus transformations are lost 140 // so we need to alter the coordinates to reflect their transformed point. 141 double xtrans = 0; 142 double ytrans = 0; 143 144 wxGCDC* gcdc = wxDynamicCast(&dc, wxGCDC); 145 wxGraphicsContext* gc = gcdc->GetGraphicsContext(); 146 gc->GetTransform().TransformPoint(&xtrans, &ytrans); 147 148 transRect.x += (int)xtrans; 149 transRect.y += (int)ytrans; 150 #endif 151 152 RECT r; 153 wxCopyRectToRECT(transRect, r); 154 155 // Unlike Mac, on MSW you draw the scrollbar piece by piece. 156 // so we draw the track first, then the buttons 157 if (hTheme) 158 { 159 engine->DrawThemeBackground(hTheme, GraphicsHDC(&dc), part, xpState, &r, 0); 160 161 int buttonSize = 16; 162 163 part = SP_BUTTON; 164 xpState = getTSStateForPart(wxSCROLLPART_BACKBTNSTART, focusPart, hoverPart, flags); 165 xpState += horiz ? TS_LEFT_BUTTON : TS_UP_BUTTON; 166 RECT buttonRect = r; 167 buttonRect.bottom = buttonRect.top + buttonSize; 168 buttonRect.right = buttonRect.left + buttonSize; 169 engine->DrawThemeBackground(hTheme, GraphicsHDC(&dc), part, xpState, &buttonRect, 0); 170 171 xpState = getTSStateForPart(wxSCROLLPART_FWDBTNEND, focusPart, hoverPart, flags); 172 xpState += horiz ? TS_RIGHT_BUTTON : TS_DOWN_BUTTON; 173 buttonRect = r; 174 buttonRect.top = buttonRect.bottom - buttonSize; 175 buttonRect.left = buttonRect.right - buttonSize; 176 engine->DrawThemeBackground(hTheme, GraphicsHDC(&dc), part, xpState, &buttonRect, 0); 177 178 part = horiz ? SP_THUMBHOR : SP_THUMBVERT; 179 180 int physicalLength = horiz ? rect.width : rect.height; 181 physicalLength -= buttonSize*2; 182 int thumbStart = 0; 183 int thumbLength = 0; 184 calcThumbStartAndLength(physicalLength, max, 185 current, step, &thumbStart, &thumbLength); 186 buttonRect = r; 187 if (horiz) { 188 buttonRect.left = buttonRect.left + thumbStart + buttonSize; 189 buttonRect.right = buttonRect.left + thumbLength; 190 } else { 191 buttonRect.top = buttonRect.top + thumbStart + buttonSize; 192 buttonRect.bottom = buttonRect.top + thumbLength; 193 } 194 195 xpState = getTSStateForPart(wxSCROLLPART_THUMB, focusPart, hoverPart, flags); 196 engine->DrawThemeBackground(hTheme, GraphicsHDC(&dc), part, xpState, &buttonRect, 0); 197 198 // draw the gripper 199 int thickness = ::GetSystemMetrics(SM_CXVSCROLL) / 2; 200 201 buttonRect.left += ((buttonRect.right - buttonRect.left) - thickness) / 2; 202 buttonRect.top += ((buttonRect.bottom - buttonRect.top) - thickness) / 2; 203 buttonRect.right = buttonRect.left + thickness; 204 buttonRect.bottom = buttonRect.top + thickness; 205 206 if (horiz) 207 part = SP_GRIPPERHOR; 208 else 209 part = SP_GRIPPERVERT; 210 211 engine->DrawThemeBackground(hTheme, GraphicsHDC(&dc), part, xpState, &buttonRect, 0); 212 } 213 } 214