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 18 namespace { 19 20 // Theme colors returned by GetSystemColor(). 21 22 // MenuItem: 23 const SkColor kMenuBackgroundColor = SK_ColorWHITE; 24 const SkColor kMenuHighlightBackgroundColor = SkColorSetRGB(0x42, 0x81, 0xF4); 25 const SkColor kMenuInvertedSchemeHighlightBackgroundColor = 26 SkColorSetRGB(48, 48, 48); 27 const SkColor kMenuBorderColor = SkColorSetRGB(0xBA, 0xBA, 0xBA); 28 const SkColor kEnabledMenuButtonBorderColor = SkColorSetARGB(36, 0, 0, 0); 29 const SkColor kFocusedMenuButtonBorderColor = SkColorSetARGB(72, 0, 0, 0); 30 const SkColor kHoverMenuButtonBorderColor = SkColorSetARGB(72, 0, 0, 0); 31 const SkColor kMenuSeparatorColor = SkColorSetRGB(0xE9, 0xE9, 0xE9); 32 const SkColor kEnabledMenuItemForegroundColor = SK_ColorBLACK; 33 const SkColor kDisabledMenuItemForegroundColor = SkColorSetRGB(161, 161, 146); 34 const SkColor kHoverMenuItemBackgroundColor = 35 SkColorSetARGB(204, 255, 255, 255); 36 // Button: 37 const SkColor kButtonHoverBackgroundColor = SkColorSetRGB(0xEA, 0xEA, 0xEA); 38 const SkColor kBlueButtonEnabledColor = SK_ColorWHITE; 39 const SkColor kBlueButtonDisabledColor = SK_ColorWHITE; 40 const SkColor kBlueButtonPressedColor = SK_ColorWHITE; 41 const SkColor kBlueButtonHoverColor = SK_ColorWHITE; 42 const SkColor kBlueButtonShadowColor = SkColorSetRGB(0x53, 0x8C, 0xEA); 43 44 } // namespace 45 46 namespace ui { 47 48 bool 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 125 gfx::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 148 void 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 154 void 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 166 void 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 175 void 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 183 void 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 208 scoped_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