Home | History | Annotate | Download | only in win
      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