Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "webkit/glue/webthemeengine_impl_win.h"
      6 
      7 #include <vsstyle.h>  // To convert to gfx::NativeTheme::State
      8 
      9 #include "base/logging.h"
     10 #include "skia/ext/platform_canvas.h"
     11 #include "skia/ext/skia_utils_win.h"
     12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
     13 #include "ui/gfx/native_theme_win.h"
     14 
     15 using WebKit::WebCanvas;
     16 using WebKit::WebColor;
     17 using WebKit::WebRect;
     18 
     19 namespace webkit_glue {
     20 
     21 static RECT WebRectToRECT(const WebRect& rect) {
     22   RECT result;
     23   result.left = rect.x;
     24   result.top = rect.y;
     25   result.right = rect.x + rect.width;
     26   result.bottom = rect.y + rect.height;
     27   return result;
     28 }
     29 
     30 static gfx::NativeTheme::State WebButtonStateToGfx(
     31     int part,
     32     int state,
     33     gfx::NativeTheme::ButtonExtraParams* extra) {
     34   gfx::NativeTheme::State gfx_state = gfx::NativeTheme::kNormal;
     35 
     36   if (part == BP_PUSHBUTTON) {
     37     switch(state) {
     38       case PBS_NORMAL:
     39         gfx_state = gfx::NativeTheme::kNormal;
     40         extra->checked = false;
     41         extra->indeterminate = false;
     42         extra->is_default = false;
     43         break;
     44       case PBS_HOT:
     45         gfx_state = gfx::NativeTheme::kHovered;
     46         extra->checked = false;
     47         extra->indeterminate = false;
     48         extra->is_default = false;
     49         break;
     50       case PBS_PRESSED:
     51         gfx_state = gfx::NativeTheme::kPressed;
     52         extra->checked = false;
     53         extra->indeterminate = false;
     54         extra->is_default = false;
     55         break;
     56       case PBS_DISABLED:
     57         gfx_state = gfx::NativeTheme::kDisabled;
     58         extra->checked = false;
     59         extra->indeterminate = false;
     60         extra->is_default = false;
     61         break;
     62       case PBS_DEFAULTED:
     63         gfx_state = gfx::NativeTheme::kNormal;
     64         extra->checked = false;
     65         extra->indeterminate = false;
     66         extra->is_default = true;
     67         break;
     68       case PBS_DEFAULTED_ANIMATING:
     69         gfx_state = gfx::NativeTheme::kNormal;
     70         extra->checked = false;
     71         extra->indeterminate = false;
     72         extra->is_default = true;
     73         break;
     74       default:
     75         NOTREACHED() << "Invalid state: " << state;
     76     }
     77   } else if (part == BP_RADIOBUTTON) {
     78     switch(state) {
     79       case RBS_UNCHECKEDNORMAL:
     80         gfx_state = gfx::NativeTheme::kNormal;
     81         extra->checked = false;
     82         extra->indeterminate = false;
     83         extra->is_default = false;
     84         break;
     85       case RBS_UNCHECKEDHOT:
     86         gfx_state = gfx::NativeTheme::kHovered;
     87         extra->checked = false;
     88         extra->indeterminate = false;
     89         extra->is_default = false;
     90         break;
     91       case RBS_UNCHECKEDPRESSED:
     92         gfx_state = gfx::NativeTheme::kPressed;
     93         extra->checked = false;
     94         extra->indeterminate = false;
     95         extra->is_default = false;
     96         break;
     97       case RBS_UNCHECKEDDISABLED:
     98         gfx_state = gfx::NativeTheme::kDisabled;
     99         extra->checked = false;
    100         extra->indeterminate = false;
    101         extra->is_default = false;
    102         break;
    103       case RBS_CHECKEDNORMAL:
    104         gfx_state = gfx::NativeTheme::kNormal;
    105         extra->checked = true;
    106         extra->indeterminate = false;
    107         extra->is_default = false;
    108         break;
    109       case RBS_CHECKEDHOT:
    110         gfx_state = gfx::NativeTheme::kHovered;
    111         extra->checked = true;
    112         extra->indeterminate = false;
    113         extra->is_default = false;
    114         break;
    115       case RBS_CHECKEDPRESSED:
    116         gfx_state = gfx::NativeTheme::kPressed;
    117         extra->checked = true;
    118         extra->indeterminate = false;
    119         extra->is_default = false;
    120         break;
    121       case RBS_CHECKEDDISABLED:
    122         gfx_state = gfx::NativeTheme::kDisabled;
    123         extra->checked = true;
    124         extra->indeterminate = false;
    125         extra->is_default = false;
    126         break;
    127       default:
    128         NOTREACHED() << "Invalid state: " << state;
    129         break;
    130     }
    131   } else if (part == BP_CHECKBOX) {
    132     switch(state) {
    133       case CBS_UNCHECKEDNORMAL:
    134         gfx_state = gfx::NativeTheme::kNormal;
    135         extra->checked = false;
    136         extra->indeterminate = false;
    137         extra->is_default = false;
    138         break;
    139       case CBS_UNCHECKEDHOT:
    140         gfx_state = gfx::NativeTheme::kHovered;
    141         extra->checked = false;
    142         extra->indeterminate = false;
    143         extra->is_default = false;
    144         break;
    145       case CBS_UNCHECKEDPRESSED:
    146         gfx_state = gfx::NativeTheme::kPressed;
    147         extra->checked = false;
    148         extra->indeterminate = false;
    149         extra->is_default = false;
    150         break;
    151       case CBS_UNCHECKEDDISABLED:
    152         gfx_state = gfx::NativeTheme::kDisabled;
    153         extra->checked = false;
    154         extra->indeterminate = false;
    155         extra->is_default = false;
    156         break;
    157       case CBS_CHECKEDNORMAL:
    158         gfx_state = gfx::NativeTheme::kNormal;
    159         extra->checked = true;
    160         extra->indeterminate = false;
    161         extra->is_default = false;
    162         break;
    163       case CBS_CHECKEDHOT:
    164         gfx_state = gfx::NativeTheme::kHovered;
    165         extra->checked = true;
    166         extra->indeterminate = false;
    167         extra->is_default = false;
    168         break;
    169       case CBS_CHECKEDPRESSED:
    170         gfx_state = gfx::NativeTheme::kPressed;
    171         extra->checked = true;
    172         extra->indeterminate = false;
    173         extra->is_default = false;
    174         break;
    175       case CBS_CHECKEDDISABLED:
    176         gfx_state = gfx::NativeTheme::kDisabled;
    177         extra->checked = true;
    178         extra->indeterminate = false;
    179         extra->is_default = false;
    180         break;
    181       case CBS_MIXEDNORMAL:
    182         gfx_state = gfx::NativeTheme::kNormal;
    183         extra->checked = false;
    184         extra->indeterminate = true;
    185         extra->is_default = false;
    186         break;
    187       case CBS_MIXEDHOT:
    188         gfx_state = gfx::NativeTheme::kHovered;
    189         extra->checked = false;
    190         extra->indeterminate = true;
    191         extra->is_default = false;
    192         break;
    193       case CBS_MIXEDPRESSED:
    194         gfx_state = gfx::NativeTheme::kPressed;
    195         extra->checked = false;
    196         extra->indeterminate = true;
    197         extra->is_default = false;
    198         break;
    199       case CBS_MIXEDDISABLED:
    200         gfx_state = gfx::NativeTheme::kDisabled;
    201         extra->checked = false;
    202         extra->indeterminate = true;
    203         extra->is_default = false;
    204         break;
    205       case CBS_IMPLICITNORMAL:
    206         gfx_state = gfx::NativeTheme::kNormal;
    207         extra->checked = false;
    208         extra->indeterminate = false;
    209         extra->is_default = false;
    210         break;
    211       case CBS_IMPLICITHOT:
    212         gfx_state = gfx::NativeTheme::kHovered;
    213         extra->checked = false;
    214         extra->indeterminate = false;
    215         extra->is_default = false;
    216         break;
    217       case CBS_IMPLICITPRESSED:
    218         gfx_state = gfx::NativeTheme::kPressed;
    219         extra->checked = false;
    220         extra->indeterminate = false;
    221         extra->is_default = false;
    222         break;
    223       case CBS_IMPLICITDISABLED:
    224         gfx_state = gfx::NativeTheme::kDisabled;
    225         extra->checked = false;
    226         extra->indeterminate = false;
    227         extra->is_default = false;
    228         break;
    229       case CBS_EXCLUDEDNORMAL:
    230         gfx_state = gfx::NativeTheme::kNormal;
    231         extra->checked = false;
    232         extra->indeterminate = false;
    233         extra->is_default = false;
    234         break;
    235       case CBS_EXCLUDEDHOT:
    236         gfx_state = gfx::NativeTheme::kHovered;
    237         extra->checked = false;
    238         extra->indeterminate = false;
    239         extra->is_default = false;
    240         break;
    241       case CBS_EXCLUDEDPRESSED:
    242         gfx_state = gfx::NativeTheme::kPressed;
    243         extra->checked = false;
    244         extra->indeterminate = false;
    245         extra->is_default = false;
    246         break;
    247       case CBS_EXCLUDEDDISABLED:
    248         gfx_state = gfx::NativeTheme::kDisabled;
    249         extra->checked = false;
    250         extra->indeterminate = false;
    251         extra->is_default = false;
    252         break;
    253       default:
    254         NOTREACHED() << "Invalid state: " << state;
    255         break;
    256     }
    257   } else if (part == BP_GROUPBOX) {
    258     switch(state) {
    259       case GBS_NORMAL:
    260         gfx_state = gfx::NativeTheme::kNormal;
    261         extra->checked = false;
    262         extra->indeterminate = false;
    263         extra->is_default = false;
    264         break;
    265       case GBS_DISABLED:
    266         gfx_state = gfx::NativeTheme::kDisabled;
    267         extra->checked = false;
    268         extra->indeterminate = false;
    269         extra->is_default = false;
    270         break;
    271       default:
    272         NOTREACHED() << "Invalid state: " << state;
    273         break;
    274     }
    275   } else if (part == BP_COMMANDLINK) {
    276     switch(state) {
    277       case CMDLS_NORMAL:
    278         gfx_state = gfx::NativeTheme::kNormal;
    279         extra->checked = false;
    280         extra->indeterminate = false;
    281         extra->is_default = false;
    282         break;
    283       case CMDLS_HOT:
    284         gfx_state = gfx::NativeTheme::kHovered;
    285         extra->checked = false;
    286         extra->indeterminate = false;
    287         extra->is_default = false;
    288         break;
    289       case CMDLS_PRESSED:
    290         gfx_state = gfx::NativeTheme::kPressed;
    291         extra->checked = false;
    292         extra->indeterminate = false;
    293         extra->is_default = false;
    294         break;
    295       case CMDLS_DISABLED:
    296         gfx_state = gfx::NativeTheme::kDisabled;
    297         extra->checked = false;
    298         extra->indeterminate = false;
    299         extra->is_default = false;
    300         break;
    301       case CMDLS_DEFAULTED:
    302         gfx_state = gfx::NativeTheme::kNormal;
    303         extra->checked = false;
    304         extra->indeterminate = false;
    305         extra->is_default = true;
    306         break;
    307       case CMDLS_DEFAULTED_ANIMATING:
    308         gfx_state = gfx::NativeTheme::kNormal;
    309         extra->checked = false;
    310         extra->indeterminate = false;
    311         extra->is_default = true;
    312         break;
    313       default:
    314         NOTREACHED() << "Invalid state: " << state;
    315         break;
    316     }
    317   } else if (part == BP_COMMANDLINKGLYPH) {
    318     switch(state) {
    319       case CMDLGS_NORMAL:
    320         gfx_state = gfx::NativeTheme::kNormal;
    321         extra->checked = false;
    322         extra->indeterminate = false;
    323         extra->is_default = false;
    324         break;
    325       case CMDLGS_HOT:
    326         gfx_state = gfx::NativeTheme::kHovered;
    327         extra->checked = false;
    328         extra->indeterminate = false;
    329         extra->is_default = false;
    330         break;
    331       case CMDLGS_PRESSED:
    332         gfx_state = gfx::NativeTheme::kPressed;
    333         extra->checked = false;
    334         extra->indeterminate = false;
    335         extra->is_default = false;
    336         break;
    337       case CMDLGS_DISABLED:
    338         gfx_state = gfx::NativeTheme::kDisabled;
    339         extra->checked = false;
    340         extra->indeterminate = false;
    341         extra->is_default = false;
    342         break;
    343       case CMDLGS_DEFAULTED:
    344         gfx_state = gfx::NativeTheme::kNormal;
    345         extra->checked = false;
    346         extra->indeterminate = false;
    347         extra->is_default = true;
    348         break;
    349       default:
    350         NOTREACHED() << "Invalid state: " << state;
    351         break;
    352     }
    353   }
    354   return gfx_state;
    355 }
    356 
    357 void WebThemeEngineImpl::paintButton(
    358     WebCanvas* canvas, int part, int state, int classic_state,
    359     const WebRect& rect) {
    360   gfx::NativeTheme::Part native_part = gfx::NativeTheme::kPushButton;
    361   switch(part) {
    362     case BP_PUSHBUTTON:
    363       native_part = gfx::NativeTheme::kPushButton;
    364       break;
    365     case BP_CHECKBOX:
    366       native_part = gfx::NativeTheme::kCheckbox;
    367       break;
    368     case BP_RADIOBUTTON:
    369       native_part = gfx::NativeTheme::kRadio;
    370       break;
    371     default:
    372       break;
    373   }
    374   gfx::NativeTheme::ExtraParams extra;
    375   gfx::NativeTheme::State native_state = WebButtonStateToGfx(part, state,
    376                                                              &extra.button);
    377   extra.button.classic_state = classic_state;
    378   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    379   gfx::NativeTheme::instance()->Paint(canvas, native_part,
    380                                       native_state, gfx_rect, extra);
    381 }
    382 
    383 void WebThemeEngineImpl::paintMenuList(
    384     WebCanvas* canvas, int part, int state, int classic_state,
    385     const WebRect& rect) {
    386   HDC hdc = skia::BeginPlatformPaint(canvas);
    387 
    388   RECT native_rect = WebRectToRECT(rect);
    389   gfx::NativeThemeWin::instance()->PaintMenuList(
    390       hdc, part, state, classic_state, &native_rect);
    391 
    392   skia::EndPlatformPaint(canvas);
    393 }
    394 
    395 void WebThemeEngineImpl::paintScrollbarArrow(
    396     WebCanvas* canvas, int state, int classic_state,
    397     const WebRect& rect) {
    398   HDC hdc = skia::BeginPlatformPaint(canvas);
    399 
    400   RECT native_rect = WebRectToRECT(rect);
    401   gfx::NativeThemeWin::instance()->PaintScrollbarArrow(
    402       hdc, state, classic_state, &native_rect);
    403 
    404   skia::EndPlatformPaint(canvas);
    405 }
    406 
    407 void WebThemeEngineImpl::paintScrollbarThumb(
    408     WebCanvas* canvas, int part, int state, int classic_state,
    409     const WebRect& rect) {
    410   HDC hdc = skia::BeginPlatformPaint(canvas);
    411 
    412   RECT native_rect = WebRectToRECT(rect);
    413   gfx::NativeThemeWin::instance()->PaintScrollbarThumb(
    414       hdc, part, state, classic_state, &native_rect);
    415 
    416   skia::EndPlatformPaint(canvas);
    417 }
    418 
    419 void WebThemeEngineImpl::paintScrollbarTrack(
    420     WebCanvas* canvas, int part, int state, int classic_state,
    421     const WebRect& rect, const WebRect& align_rect) {
    422   HDC hdc = skia::BeginPlatformPaint(canvas);
    423 
    424   RECT native_rect = WebRectToRECT(rect);
    425   RECT native_align_rect = WebRectToRECT(align_rect);
    426   gfx::NativeThemeWin::instance()->PaintScrollbarTrack(
    427       hdc, part, state, classic_state, &native_rect, &native_align_rect,
    428       canvas);
    429 
    430   skia::EndPlatformPaint(canvas);
    431 }
    432 
    433 void WebThemeEngineImpl::paintSpinButton(
    434     WebCanvas* canvas, int part, int state, int classic_state,
    435     const WebRect& rect) {
    436   HDC hdc = skia::BeginPlatformPaint(canvas);
    437 
    438   RECT native_rect = WebRectToRECT(rect);
    439   gfx::NativeThemeWin::instance()->PaintSpinButton(
    440       hdc, part, state, classic_state, &native_rect);
    441 
    442   skia::EndPlatformPaint(canvas);
    443 }
    444 
    445 void WebThemeEngineImpl::paintTextField(
    446     WebCanvas* canvas, int part, int state, int classic_state,
    447     const WebRect& rect, WebColor color, bool fill_content_area,
    448     bool draw_edges) {
    449   HDC hdc = skia::BeginPlatformPaint(canvas);
    450 
    451   RECT native_rect = WebRectToRECT(rect);
    452   COLORREF c = skia::SkColorToCOLORREF(color);
    453 
    454   gfx::NativeThemeWin::instance()->PaintTextField(
    455       hdc, part, state, classic_state, &native_rect, c, fill_content_area,
    456       draw_edges);
    457 
    458   skia::EndPlatformPaint(canvas);
    459 }
    460 
    461 void WebThemeEngineImpl::paintTrackbar(
    462     WebCanvas* canvas, int part, int state, int classic_state,
    463     const WebRect& rect) {
    464   HDC hdc = skia::BeginPlatformPaint(canvas);
    465 
    466   RECT native_rect = WebRectToRECT(rect);
    467   gfx::NativeThemeWin::instance()->PaintTrackbar(
    468       hdc, part, state, classic_state, &native_rect, canvas);
    469 
    470   skia::EndPlatformPaint(canvas);
    471 }
    472 
    473 void WebThemeEngineImpl::paintProgressBar(
    474     WebCanvas* canvas, const WebRect& barRect, const WebRect& valueRect,
    475     bool determinate, double animatedSeconds)
    476 {
    477   HDC hdc = skia::BeginPlatformPaint(canvas);
    478 
    479   RECT native_bar_rect = WebRectToRECT(barRect);
    480   RECT native_value_rect = WebRectToRECT(valueRect);
    481   gfx::NativeThemeWin::instance()->PaintProgressBar(
    482       hdc, &native_bar_rect,
    483       &native_value_rect, determinate, animatedSeconds, canvas);
    484 
    485   skia::EndPlatformPaint(canvas);
    486 }
    487 
    488 }  // namespace webkit_glue
    489