| OLD | NEW |
| (Empty) |
| 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/native_theme_aura.h" | |
| 6 | |
| 7 #include <limits> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "ui/base/layout.h" | |
| 11 #include "ui/base/nine_image_painter_factory.h" | |
| 12 #include "ui/gfx/canvas.h" | |
| 13 #include "ui/gfx/image/image_skia.h" | |
| 14 #include "ui/gfx/nine_image_painter.h" | |
| 15 #include "ui/gfx/path.h" | |
| 16 #include "ui/gfx/rect.h" | |
| 17 #include "ui/gfx/size.h" | |
| 18 #include "ui/gfx/skbitmap_operations.h" | |
| 19 #include "ui/gfx/skia_util.h" | |
| 20 #include "ui/native_theme/common_theme.h" | |
| 21 #include "ui/native_theme/native_theme_switches.h" | |
| 22 #include "ui/resources/grit/ui_resources.h" | |
| 23 | |
| 24 using gfx::NineImagePainter; | |
| 25 | |
| 26 #define EMPTY_IMAGE_GRID { 0, 0, 0, 0, 0, 0, 0, 0, 0 } | |
| 27 | |
| 28 namespace ui { | |
| 29 | |
| 30 namespace { | |
| 31 | |
| 32 const int kScrollbarThumbImages[NativeTheme::kNumStates][9] = { | |
| 33 EMPTY_IMAGE_GRID, | |
| 34 IMAGE_GRID(IDR_SCROLLBAR_THUMB_BASE_HOVER), | |
| 35 IMAGE_GRID(IDR_SCROLLBAR_THUMB_BASE_NORMAL), | |
| 36 IMAGE_GRID(IDR_SCROLLBAR_THUMB_BASE_PRESSED) | |
| 37 }; | |
| 38 | |
| 39 const int kScrollbarArrowButtonImages[NativeTheme::kNumStates][9] = { | |
| 40 EMPTY_IMAGE_GRID, | |
| 41 IMAGE_GRID(IDR_SCROLLBAR_ARROW_BUTTON_BASE_HOVER), | |
| 42 IMAGE_GRID(IDR_SCROLLBAR_ARROW_BUTTON_BASE_NORMAL), | |
| 43 IMAGE_GRID(IDR_SCROLLBAR_ARROW_BUTTON_BASE_PRESSED) | |
| 44 }; | |
| 45 | |
| 46 const uint8 kScrollbarOverlayThumbFillAlphas[NativeTheme::kNumStates] = { | |
| 47 0, // Does not matter, will not paint for disabled state. | |
| 48 178, // Hover state, opacity 70%, alpha would be 0.7 * 255. | |
| 49 140, // Normal state, opacity 55%, alpha would be 0.55 * 255. | |
| 50 178 // Pressed state, opacity 70%, alpha would be 0.7 * 255. | |
| 51 }; | |
| 52 | |
| 53 const uint8 kScrollbarOverlayThumbStrokeAlphas[NativeTheme::kNumStates] = { | |
| 54 0, // Does not matter, will not paint for disabled state. | |
| 55 51, // Hover state, opacity 20%, alpha would be 0.2 * 255. | |
| 56 38, // Normal state, opacity 15%, alpha would be 0.15 * 255. | |
| 57 51 // Pressed state, opacity 20%, alpha would be 0.2 * 255. | |
| 58 }; | |
| 59 | |
| 60 const int kScrollbarOverlayThumbStrokeImages[9] = | |
| 61 IMAGE_GRID_NO_CENTER(IDR_SCROLLBAR_OVERLAY_THUMB_STROKE); | |
| 62 | |
| 63 const int kScrollbarOverlayThumbFillImages[9] = | |
| 64 IMAGE_GRID(IDR_SCROLLBAR_OVERLAY_THUMB_FILL); | |
| 65 | |
| 66 const int kScrollbarTrackImages[9] = IMAGE_GRID(IDR_SCROLLBAR_BASE); | |
| 67 | |
| 68 } // namespace | |
| 69 | |
| 70 #if !defined(OS_WIN) | |
| 71 // static | |
| 72 NativeTheme* NativeTheme::instance() { | |
| 73 return NativeThemeAura::instance(); | |
| 74 } | |
| 75 | |
| 76 // static | |
| 77 NativeThemeAura* NativeThemeAura::instance() { | |
| 78 CR_DEFINE_STATIC_LOCAL(NativeThemeAura, s_native_theme, ()); | |
| 79 return &s_native_theme; | |
| 80 } | |
| 81 #endif | |
| 82 | |
| 83 NativeThemeAura::NativeThemeAura() { | |
| 84 // We don't draw scrollbar buttons. | |
| 85 #if defined(OS_CHROMEOS) | |
| 86 set_scrollbar_button_length(0); | |
| 87 #endif | |
| 88 | |
| 89 // Images and alphas declarations assume the following order. | |
| 90 COMPILE_ASSERT(kDisabled == 0, states_unexpectedly_changed); | |
| 91 COMPILE_ASSERT(kHovered == 1, states_unexpectedly_changed); | |
| 92 COMPILE_ASSERT(kNormal == 2, states_unexpectedly_changed); | |
| 93 COMPILE_ASSERT(kPressed == 3, states_unexpectedly_changed); | |
| 94 } | |
| 95 | |
| 96 NativeThemeAura::~NativeThemeAura() { | |
| 97 } | |
| 98 | |
| 99 void NativeThemeAura::PaintMenuPopupBackground( | |
| 100 SkCanvas* canvas, | |
| 101 const gfx::Size& size, | |
| 102 const MenuBackgroundExtraParams& menu_background) const { | |
| 103 SkColor color = GetSystemColor(NativeTheme::kColorId_MenuBackgroundColor); | |
| 104 if (menu_background.corner_radius > 0) { | |
| 105 SkPaint paint; | |
| 106 paint.setStyle(SkPaint::kFill_Style); | |
| 107 paint.setFlags(SkPaint::kAntiAlias_Flag); | |
| 108 paint.setColor(color); | |
| 109 | |
| 110 gfx::Path path; | |
| 111 SkRect rect = SkRect::MakeWH(SkIntToScalar(size.width()), | |
| 112 SkIntToScalar(size.height())); | |
| 113 SkScalar radius = SkIntToScalar(menu_background.corner_radius); | |
| 114 SkScalar radii[8] = {radius, radius, radius, radius, | |
| 115 radius, radius, radius, radius}; | |
| 116 path.addRoundRect(rect, radii); | |
| 117 | |
| 118 canvas->drawPath(path, paint); | |
| 119 } else { | |
| 120 canvas->drawColor(color, SkXfermode::kSrc_Mode); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 void NativeThemeAura::PaintMenuItemBackground( | |
| 125 SkCanvas* canvas, | |
| 126 State state, | |
| 127 const gfx::Rect& rect, | |
| 128 const MenuListExtraParams& menu_list) const { | |
| 129 CommonThemePaintMenuItemBackground(canvas, state, rect); | |
| 130 } | |
| 131 | |
| 132 void NativeThemeAura::PaintArrowButton( | |
| 133 SkCanvas* gc, | |
| 134 const gfx::Rect& rect, | |
| 135 Part direction, | |
| 136 State state) const { | |
| 137 if (direction == kInnerSpinButton) { | |
| 138 FallbackTheme::PaintArrowButton(gc, rect, direction, state); | |
| 139 return; | |
| 140 } | |
| 141 PaintPainter(GetOrCreatePainter( | |
| 142 kScrollbarArrowButtonImages, state, | |
| 143 scrollbar_arrow_button_painters_), | |
| 144 gc, rect); | |
| 145 | |
| 146 // Aura-win uses slightly different arrow colors. | |
| 147 SkColor arrow_color = GetArrowColor(state); | |
| 148 switch (state) { | |
| 149 case kHovered: | |
| 150 case kNormal: | |
| 151 arrow_color = SkColorSetRGB(0x50, 0x50, 0x50); | |
| 152 break; | |
| 153 case kPressed: | |
| 154 arrow_color = SK_ColorWHITE; | |
| 155 default: | |
| 156 break; | |
| 157 } | |
| 158 PaintArrow(gc, rect, direction, arrow_color); | |
| 159 } | |
| 160 | |
| 161 void NativeThemeAura::PaintScrollbarTrack( | |
| 162 SkCanvas* sk_canvas, | |
| 163 Part part, | |
| 164 State state, | |
| 165 const ScrollbarTrackExtraParams& extra_params, | |
| 166 const gfx::Rect& rect) const { | |
| 167 // Overlay Scrollbar should never paint a scrollbar track. | |
| 168 DCHECK(!IsOverlayScrollbarEnabled()); | |
| 169 if (!scrollbar_track_painter_) | |
| 170 scrollbar_track_painter_ = CreateNineImagePainter(kScrollbarTrackImages); | |
| 171 PaintPainter(scrollbar_track_painter_.get(), sk_canvas, rect); | |
| 172 } | |
| 173 | |
| 174 void NativeThemeAura::PaintScrollbarThumb(SkCanvas* sk_canvas, | |
| 175 Part part, | |
| 176 State state, | |
| 177 const gfx::Rect& rect) const { | |
| 178 gfx::Rect thumb_rect(rect); | |
| 179 if (IsOverlayScrollbarEnabled()) { | |
| 180 // Overlay scrollbar has no track, just paint thumb directly. | |
| 181 // Do not paint if state is disabled. | |
| 182 if (state == kDisabled) | |
| 183 return; | |
| 184 | |
| 185 if (!scrollbar_overlay_thumb_painter_) { | |
| 186 scrollbar_overlay_thumb_painter_ = | |
| 187 CreateDualPainter(kScrollbarOverlayThumbFillImages, | |
| 188 kScrollbarOverlayThumbFillAlphas, | |
| 189 kScrollbarOverlayThumbStrokeImages, | |
| 190 kScrollbarOverlayThumbStrokeAlphas); | |
| 191 } | |
| 192 | |
| 193 PaintDualPainter( | |
| 194 scrollbar_overlay_thumb_painter_.get(), sk_canvas, thumb_rect, state); | |
| 195 return; | |
| 196 } | |
| 197 // If there are no scrollbuttons then provide some padding so that thumb | |
| 198 // doesn't touch the top of the track. | |
| 199 const int extra_padding = (scrollbar_button_length() == 0) ? 2 : 0; | |
| 200 if (part == NativeTheme::kScrollbarVerticalThumb) | |
| 201 thumb_rect.Inset(2, extra_padding, 2, extra_padding); | |
| 202 else | |
| 203 thumb_rect.Inset(extra_padding, 2, extra_padding, 2); | |
| 204 PaintPainter(GetOrCreatePainter( | |
| 205 kScrollbarThumbImages, state, scrollbar_thumb_painters_), | |
| 206 sk_canvas, | |
| 207 thumb_rect); | |
| 208 } | |
| 209 | |
| 210 void NativeThemeAura::PaintScrollbarThumbStateTransition( | |
| 211 SkCanvas* canvas, | |
| 212 State startState, | |
| 213 State endState, | |
| 214 double progress, | |
| 215 const gfx::Rect& rect) const { | |
| 216 // Only Overlay scrollbars should have state transition animation. | |
| 217 DCHECK(IsOverlayScrollbarEnabled()); | |
| 218 if (!scrollbar_overlay_thumb_painter_) { | |
| 219 scrollbar_overlay_thumb_painter_ = | |
| 220 CreateDualPainter(kScrollbarOverlayThumbFillImages, | |
| 221 kScrollbarOverlayThumbFillAlphas, | |
| 222 kScrollbarOverlayThumbStrokeImages, | |
| 223 kScrollbarOverlayThumbStrokeAlphas); | |
| 224 } | |
| 225 | |
| 226 PaintDualPainterTransition(scrollbar_overlay_thumb_painter_.get(), | |
| 227 canvas, | |
| 228 rect, | |
| 229 startState, | |
| 230 endState, | |
| 231 progress); | |
| 232 } | |
| 233 | |
| 234 void NativeThemeAura::PaintScrollbarCorner(SkCanvas* canvas, | |
| 235 State state, | |
| 236 const gfx::Rect& rect) const { | |
| 237 // Overlay Scrollbar should never paint a scrollbar corner. | |
| 238 DCHECK(!IsOverlayScrollbarEnabled()); | |
| 239 SkPaint paint; | |
| 240 paint.setColor(SkColorSetRGB(0xF1, 0xF1, 0xF1)); | |
| 241 paint.setStyle(SkPaint::kFill_Style); | |
| 242 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | |
| 243 canvas->drawIRect(RectToSkIRect(rect), paint); | |
| 244 } | |
| 245 | |
| 246 NineImagePainter* NativeThemeAura::GetOrCreatePainter( | |
| 247 const int images[kNumStates][9], | |
| 248 State state, | |
| 249 scoped_ptr<NineImagePainter> painters[kNumStates]) const { | |
| 250 if (painters[state]) | |
| 251 return painters[state].get(); | |
| 252 if (images[state][0] == 0) { | |
| 253 // Must always provide normal state images. | |
| 254 DCHECK_NE(kNormal, state); | |
| 255 return GetOrCreatePainter(images, kNormal, painters); | |
| 256 } | |
| 257 painters[state] = CreateNineImagePainter(images[state]); | |
| 258 return painters[state].get(); | |
| 259 } | |
| 260 | |
| 261 void NativeThemeAura::PaintPainter(NineImagePainter* painter, | |
| 262 SkCanvas* sk_canvas, | |
| 263 const gfx::Rect& rect) const { | |
| 264 DCHECK(painter); | |
| 265 scoped_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(sk_canvas)); | |
| 266 painter->Paint(canvas.get(), rect); | |
| 267 } | |
| 268 | |
| 269 scoped_ptr<NativeThemeAura::DualPainter> NativeThemeAura::CreateDualPainter( | |
| 270 const int fill_image_ids[9], | |
| 271 const uint8 fill_alphas[kNumStates], | |
| 272 const int stroke_image_ids[9], | |
| 273 const uint8 stroke_alphas[kNumStates]) const { | |
| 274 scoped_ptr<NativeThemeAura::DualPainter> dual_painter( | |
| 275 new NativeThemeAura::DualPainter(CreateNineImagePainter(fill_image_ids), | |
| 276 fill_alphas, | |
| 277 CreateNineImagePainter(stroke_image_ids), | |
| 278 stroke_alphas)); | |
| 279 return dual_painter.Pass(); | |
| 280 } | |
| 281 | |
| 282 void NativeThemeAura::PaintDualPainter( | |
| 283 NativeThemeAura::DualPainter* dual_painter, | |
| 284 SkCanvas* sk_canvas, | |
| 285 const gfx::Rect& rect, | |
| 286 State state) const { | |
| 287 DCHECK(dual_painter); | |
| 288 scoped_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(sk_canvas)); | |
| 289 dual_painter->fill_painter->Paint( | |
| 290 canvas.get(), rect, dual_painter->fill_alphas[state]); | |
| 291 dual_painter->stroke_painter->Paint( | |
| 292 canvas.get(), rect, dual_painter->stroke_alphas[state]); | |
| 293 } | |
| 294 | |
| 295 void NativeThemeAura::PaintDualPainterTransition( | |
| 296 NativeThemeAura::DualPainter* dual_painter, | |
| 297 SkCanvas* sk_canvas, | |
| 298 const gfx::Rect& rect, | |
| 299 State startState, | |
| 300 State endState, | |
| 301 double progress) const { | |
| 302 DCHECK(dual_painter); | |
| 303 scoped_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(sk_canvas)); | |
| 304 uint8 fill_alpha = dual_painter->fill_alphas[startState] + | |
| 305 (dual_painter->fill_alphas[endState] - | |
| 306 dual_painter->fill_alphas[startState]) * | |
| 307 progress; | |
| 308 uint8 stroke_alpha = dual_painter->stroke_alphas[startState] + | |
| 309 (dual_painter->stroke_alphas[endState] - | |
| 310 dual_painter->stroke_alphas[startState]) * | |
| 311 progress; | |
| 312 | |
| 313 dual_painter->fill_painter->Paint(canvas.get(), rect, fill_alpha); | |
| 314 dual_painter->stroke_painter->Paint(canvas.get(), rect, stroke_alpha); | |
| 315 } | |
| 316 | |
| 317 NativeThemeAura::DualPainter::DualPainter( | |
| 318 scoped_ptr<NineImagePainter> fill_painter, | |
| 319 const uint8 fill_alphas[kNumStates], | |
| 320 scoped_ptr<NineImagePainter> stroke_painter, | |
| 321 const uint8 stroke_alphas[kNumStates]) | |
| 322 : fill_painter(fill_painter.Pass()), | |
| 323 fill_alphas(fill_alphas), | |
| 324 stroke_painter(stroke_painter.Pass()), | |
| 325 stroke_alphas(stroke_alphas) {} | |
| 326 | |
| 327 NativeThemeAura::DualPainter::~DualPainter() {} | |
| 328 | |
| 329 } // namespace ui | |
| OLD | NEW |