1// Copyright (c) 2012 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 "ui/native_theme/common_theme.h"
6
7#include "base/logging.h"
8#include "third_party/skia/include/core/SkCanvas.h"
9#include "ui/base/resource/resource_bundle.h"
10#include "ui/gfx/canvas.h"
11#include "ui/gfx/color_utils.h"
12#include "ui/gfx/image/image_skia.h"
13#include "ui/gfx/rect.h"
14#include "ui/gfx/skia_util.h"
15#include "ui/gfx/sys_color_change_listener.h"
16#include "ui/resources/grit/ui_resources.h"
17
18namespace {
19
20// Theme colors returned by GetSystemColor().
21
22// MenuItem:
23const SkColor kMenuBackgroundColor = SK_ColorWHITE;
24const SkColor kMenuHighlightBackgroundColor = SkColorSetRGB(0x42, 0x81, 0xF4);
25const SkColor kMenuInvertedSchemeHighlightBackgroundColor =
26    SkColorSetRGB(48, 48, 48);
27const SkColor kMenuBorderColor = SkColorSetRGB(0xBA, 0xBA, 0xBA);
28const SkColor kEnabledMenuButtonBorderColor = SkColorSetARGB(36, 0, 0, 0);
29const SkColor kFocusedMenuButtonBorderColor = SkColorSetARGB(72, 0, 0, 0);
30const SkColor kHoverMenuButtonBorderColor = SkColorSetARGB(72, 0, 0, 0);
31const SkColor kMenuSeparatorColor = SkColorSetRGB(0xE9, 0xE9, 0xE9);
32const SkColor kEnabledMenuItemForegroundColor = SK_ColorBLACK;
33const SkColor kDisabledMenuItemForegroundColor = SkColorSetRGB(161, 161, 146);
34const SkColor kHoverMenuItemBackgroundColor =
35    SkColorSetARGB(204, 255, 255, 255);
36// Button:
37const SkColor kButtonHoverBackgroundColor = SkColorSetRGB(0xEA, 0xEA, 0xEA);
38const SkColor kBlueButtonEnabledColor = SK_ColorWHITE;
39const SkColor kBlueButtonDisabledColor = SK_ColorWHITE;
40const SkColor kBlueButtonPressedColor = SK_ColorWHITE;
41const SkColor kBlueButtonHoverColor = SK_ColorWHITE;
42const SkColor kBlueButtonShadowColor = SkColorSetRGB(0x53, 0x8C, 0xEA);
43
44}  // namespace
45
46namespace ui {
47
48bool CommonThemeGetSystemColor(NativeTheme::ColorId color_id, SkColor* color) {
49  switch (color_id) {
50    // MenuItem
51    case NativeTheme::kColorId_MenuBorderColor:
52      *color = kMenuBorderColor;
53      break;
54    case NativeTheme::kColorId_EnabledMenuButtonBorderColor:
55      *color = kEnabledMenuButtonBorderColor;
56      break;
57    case NativeTheme::kColorId_FocusedMenuButtonBorderColor:
58      *color = kFocusedMenuButtonBorderColor;
59      break;
60    case NativeTheme::kColorId_HoverMenuButtonBorderColor:
61      *color = kHoverMenuButtonBorderColor;
62      break;
63    case NativeTheme::kColorId_MenuSeparatorColor:
64      *color = kMenuSeparatorColor;
65      break;
66    case NativeTheme::kColorId_MenuBackgroundColor:
67      *color = kMenuBackgroundColor;
68      break;
69    case NativeTheme::kColorId_FocusedMenuItemBackgroundColor:
70      *color = kMenuHighlightBackgroundColor;
71      break;
72    case NativeTheme::kColorId_HoverMenuItemBackgroundColor:
73      *color = kHoverMenuItemBackgroundColor;
74      break;
75    case NativeTheme::kColorId_EnabledMenuItemForegroundColor:
76      *color = kEnabledMenuItemForegroundColor;
77      break;
78    case NativeTheme::kColorId_DisabledMenuItemForegroundColor:
79      *color = kDisabledMenuItemForegroundColor;
80      break;
81    case NativeTheme::kColorId_DisabledEmphasizedMenuItemForegroundColor:
82      *color = SK_ColorBLACK;
83      break;
84    case NativeTheme::kColorId_SelectedMenuItemForegroundColor:
85      *color = SK_ColorWHITE;
86      break;
87    case NativeTheme::kColorId_ButtonDisabledColor:
88      *color = kDisabledMenuItemForegroundColor;
89      break;
90    // Button
91    case NativeTheme::kColorId_ButtonHoverBackgroundColor:
92      *color = kButtonHoverBackgroundColor;
93      break;
94    case NativeTheme::kColorId_BlueButtonEnabledColor:
95      *color = kBlueButtonEnabledColor;
96      break;
97    case NativeTheme::kColorId_BlueButtonDisabledColor:
98      *color = kBlueButtonDisabledColor;
99      break;
100    case NativeTheme::kColorId_BlueButtonPressedColor:
101      *color = kBlueButtonPressedColor;
102      break;
103    case NativeTheme::kColorId_BlueButtonHoverColor:
104      *color = kBlueButtonHoverColor;
105      break;
106    case NativeTheme::kColorId_BlueButtonShadowColor:
107      *color = kBlueButtonShadowColor;
108      break;
109    default:
110      return false;
111  }
112
113  if (gfx::IsInvertedColorScheme()) {
114    switch (color_id) {
115      case NativeTheme::kColorId_FocusedMenuItemBackgroundColor:
116        *color = kMenuInvertedSchemeHighlightBackgroundColor;
117        break;
118      default:
119        *color = color_utils::InvertColor(*color);
120    }
121  }
122  return true;
123}
124
125gfx::Size CommonThemeGetPartSize(NativeTheme::Part part,
126                                 NativeTheme::State state,
127                                 const NativeTheme::ExtraParams& extra) {
128  gfx::Size size;
129  switch (part) {
130    case NativeTheme::kComboboxArrow:
131      return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
132          IDR_MENU_DROPARROW).Size();
133
134    case NativeTheme::kMenuCheck: {
135      const gfx::ImageSkia* check =
136          ui::ResourceBundle::GetSharedInstance().GetImageNamed(
137              IDR_MENU_CHECK_CHECKED).ToImageSkia();
138      size.SetSize(check->width(), check->height());
139      break;
140    }
141    default:
142      break;
143  }
144
145  return size;
146}
147
148void CommonThemePaintComboboxArrow(SkCanvas* canvas, const gfx::Rect& rect) {
149  gfx::ImageSkia* arrow = ui::ResourceBundle::GetSharedInstance().
150      GetImageSkiaNamed(IDR_MENU_DROPARROW);
151  CommonThemeCreateCanvas(canvas)->DrawImageInt(*arrow, rect.x(), rect.y());
152}
153
154void CommonThemePaintMenuSeparator(
155    SkCanvas* canvas,
156    const gfx::Rect& rect,
157    const NativeTheme::MenuSeparatorExtraParams& extra) {
158  SkColor color;
159  CommonThemeGetSystemColor(NativeTheme::kColorId_MenuSeparatorColor, &color);
160  SkPaint paint;
161  paint.setColor(kMenuSeparatorColor);
162  int position_y = rect.y() + rect.height() / 2;
163  canvas->drawLine(rect.x(), position_y, rect.right(), position_y, paint);
164}
165
166void CommonThemePaintMenuGutter(SkCanvas* canvas, const gfx::Rect& rect) {
167  SkColor color;
168  CommonThemeGetSystemColor(NativeTheme::kColorId_MenuSeparatorColor, &color);
169  SkPaint paint;
170  paint.setColor(kMenuSeparatorColor);
171  int position_x = rect.x() + rect.width() / 2;
172  canvas->drawLine(position_x, rect.y(), position_x, rect.bottom(), paint);
173}
174
175void CommonThemePaintMenuBackground(SkCanvas* canvas, const gfx::Rect& rect) {
176  SkColor color;
177  CommonThemeGetSystemColor(NativeTheme::kColorId_MenuBackgroundColor, &color);
178  SkPaint paint;
179  paint.setColor(color);
180  canvas->drawRect(gfx::RectToSkRect(rect), paint);
181}
182
183void CommonThemePaintMenuItemBackground(SkCanvas* canvas,
184                                        NativeTheme::State state,
185                                        const gfx::Rect& rect) {
186  SkColor color;
187  SkPaint paint;
188  switch (state) {
189    case NativeTheme::kNormal:
190    case NativeTheme::kDisabled:
191      CommonThemeGetSystemColor(NativeTheme::kColorId_MenuBackgroundColor,
192                                &color);
193      paint.setColor(color);
194      break;
195    case NativeTheme::kHovered:
196      CommonThemeGetSystemColor(
197          NativeTheme::kColorId_FocusedMenuItemBackgroundColor, &color);
198      paint.setColor(color);
199      break;
200    default:
201      NOTREACHED() << "Invalid state " << state;
202      break;
203  }
204  canvas->drawRect(gfx::RectToSkRect(rect), paint);
205}
206
207// static
208scoped_ptr<gfx::Canvas> CommonThemeCreateCanvas(SkCanvas* sk_canvas) {
209  // TODO(pkotwicz): Do something better and don't infer device
210  // scale factor from canvas scale.
211  SkMatrix m = sk_canvas->getTotalMatrix();
212  float device_scale = static_cast<float>(SkScalarAbs(m.getScaleX()));
213  return scoped_ptr<gfx::Canvas>(
214      gfx::Canvas::CreateCanvasWithoutScaling(sk_canvas, device_scale));
215}
216
217}  // namespace ui
218