Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/native_theme/native_theme_aura.h" | 5 #include "ui/native_theme/native_theme_aura.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 12 #include "ui/base/layout.h" | 12 #include "ui/base/layout.h" |
| 13 #include "ui/base/nine_image_painter_factory.h" | |
| 14 #include "ui/base/resource/material_design/material_design_controller.h" | 13 #include "ui/base/resource/material_design/material_design_controller.h" |
| 14 #include "ui/gfx/animation/tween.h" | |
| 15 #include "ui/gfx/canvas.h" | 15 #include "ui/gfx/canvas.h" |
| 16 #include "ui/gfx/color_palette.h" | |
| 16 #include "ui/gfx/geometry/rect.h" | 17 #include "ui/gfx/geometry/rect.h" |
| 17 #include "ui/gfx/geometry/size.h" | 18 #include "ui/gfx/geometry/size.h" |
| 18 #include "ui/gfx/image/image_skia.h" | 19 #include "ui/gfx/image/image_skia.h" |
| 19 #include "ui/gfx/nine_image_painter.h" | |
| 20 #include "ui/gfx/path.h" | 20 #include "ui/gfx/path.h" |
| 21 #include "ui/gfx/skbitmap_operations.h" | |
| 22 #include "ui/gfx/skia_util.h" | 21 #include "ui/gfx/skia_util.h" |
| 23 #include "ui/native_theme/common_theme.h" | 22 #include "ui/native_theme/common_theme.h" |
| 24 #include "ui/native_theme/native_theme_switches.h" | 23 #include "ui/native_theme/native_theme_switches.h" |
| 25 #include "ui/resources/grit/ui_resources.h" | |
| 26 | |
| 27 using gfx::NineImagePainter; | |
| 28 | |
| 29 #define EMPTY_IMAGE_GRID { 0, 0, 0, 0, 0, 0, 0, 0, 0 } | |
| 30 | 24 |
| 31 namespace ui { | 25 namespace ui { |
| 32 | 26 |
| 33 namespace { | 27 namespace { |
| 34 | 28 |
| 35 const int kScrollbarThumbImages[NativeTheme::kNumStates][9] = { | 29 SkAlpha ThumbAlphaForState(NativeTheme::State state) { |
| 36 EMPTY_IMAGE_GRID, | 30 bool overlay = IsOverlayScrollbarEnabled(); |
| 37 IMAGE_GRID(IDR_SCROLLBAR_THUMB_BASE_HOVER), | 31 switch (state) { |
| 38 IMAGE_GRID(IDR_SCROLLBAR_THUMB_BASE_NORMAL), | 32 case NativeTheme::kDisabled: |
| 39 IMAGE_GRID(IDR_SCROLLBAR_THUMB_BASE_PRESSED) | 33 return 0x00; |
| 40 }; | 34 case NativeTheme::kHovered: |
| 35 return overlay ? 0xB2 : 0x4D; | |
| 36 case NativeTheme::kNormal: | |
| 37 return overlay ? 0x8C : 0x33; | |
| 38 case NativeTheme::kPressed: | |
| 39 return overlay ? 0xB2 : 0x80; | |
| 40 case NativeTheme::kNumStates: | |
| 41 break; | |
| 42 } | |
| 41 | 43 |
| 42 const int kScrollbarArrowButtonImages[NativeTheme::kNumStates][9] = { | 44 NOTREACHED(); |
| 43 EMPTY_IMAGE_GRID, | 45 return 0xFF; |
| 44 IMAGE_GRID(IDR_SCROLLBAR_ARROW_BUTTON_BASE_HOVER), | 46 } |
| 45 IMAGE_GRID(IDR_SCROLLBAR_ARROW_BUTTON_BASE_NORMAL), | |
| 46 IMAGE_GRID(IDR_SCROLLBAR_ARROW_BUTTON_BASE_PRESSED) | |
| 47 }; | |
| 48 | 47 |
| 49 const uint8_t kScrollbarOverlayThumbFillAlphas[NativeTheme::kNumStates] = { | 48 SkAlpha ThumbStrokeAlphaForState(NativeTheme::State state) { |
| 50 0, // Does not matter, will not paint for disabled state. | 49 DCHECK(IsOverlayScrollbarEnabled()); |
| 51 178, // Hover state, opacity 70%, alpha would be 0.7 * 255. | 50 switch (state) { |
| 52 140, // Normal state, opacity 55%, alpha would be 0.55 * 255. | 51 case NativeTheme::kDisabled: |
| 53 178 // Pressed state, opacity 70%, alpha would be 0.7 * 255. | 52 return 0x00; |
| 54 }; | 53 case NativeTheme::kHovered: |
| 54 case NativeTheme::kPressed: | |
| 55 return 0x33; | |
| 56 case NativeTheme::kNormal: | |
| 57 return 0x26; | |
| 58 case NativeTheme::kNumStates: | |
| 59 break; | |
| 60 } | |
| 55 | 61 |
| 56 const uint8_t kScrollbarOverlayThumbStrokeAlphas[NativeTheme::kNumStates] = { | 62 NOTREACHED(); |
| 57 0, // Does not matter, will not paint for disabled state. | 63 return 0xFF; |
| 58 51, // Hover state, opacity 20%, alpha would be 0.2 * 255. | 64 } |
| 59 38, // Normal state, opacity 15%, alpha would be 0.15 * 255. | |
| 60 51 // Pressed state, opacity 20%, alpha would be 0.2 * 255. | |
| 61 }; | |
| 62 | 65 |
| 63 const int kScrollbarOverlayThumbStrokeImages[9] = | 66 const SkColor kTrackColor = SkColorSetRGB(0xF1, 0xF1, 0xF1); |
| 64 IMAGE_GRID_NO_CENTER(IDR_SCROLLBAR_OVERLAY_THUMB_STROKE); | |
| 65 | |
| 66 const int kScrollbarOverlayThumbFillImages[9] = | |
| 67 IMAGE_GRID(IDR_SCROLLBAR_OVERLAY_THUMB_FILL); | |
| 68 | |
| 69 const int kScrollbarTrackImages[9] = IMAGE_GRID(IDR_SCROLLBAR_BASE); | |
| 70 | 67 |
| 71 } // namespace | 68 } // namespace |
| 72 | 69 |
| 73 #if !defined(OS_WIN) | 70 #if !defined(OS_WIN) |
| 74 // static | 71 // static |
| 75 NativeTheme* NativeTheme::GetInstanceForWeb() { | 72 NativeTheme* NativeTheme::GetInstanceForWeb() { |
| 76 return NativeThemeAura::instance(); | 73 return NativeThemeAura::instance(); |
| 77 } | 74 } |
| 78 | 75 |
| 79 // static | 76 // static |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 } | 127 } |
| 131 | 128 |
| 132 void NativeThemeAura::PaintMenuItemBackground( | 129 void NativeThemeAura::PaintMenuItemBackground( |
| 133 SkCanvas* canvas, | 130 SkCanvas* canvas, |
| 134 State state, | 131 State state, |
| 135 const gfx::Rect& rect, | 132 const gfx::Rect& rect, |
| 136 const MenuListExtraParams& menu_list) const { | 133 const MenuListExtraParams& menu_list) const { |
| 137 CommonThemePaintMenuItemBackground(canvas, state, rect); | 134 CommonThemePaintMenuItemBackground(canvas, state, rect); |
| 138 } | 135 } |
| 139 | 136 |
| 140 void NativeThemeAura::PaintArrowButton( | 137 void NativeThemeAura::PaintArrowButton(SkCanvas* canvas, |
| 141 SkCanvas* gc, | 138 const gfx::Rect& rect, |
| 142 const gfx::Rect& rect, | 139 Part direction, |
| 143 Part direction, | 140 State state) const { |
| 144 State state) const { | 141 SkColor bg_color = kTrackColor; |
| 145 if (direction == kInnerSpinButton) { | |
| 146 NativeThemeBase::PaintArrowButton(gc, rect, direction, state); | |
| 147 return; | |
| 148 } | |
| 149 PaintPainter(GetOrCreatePainter( | |
| 150 kScrollbarArrowButtonImages, state, | |
| 151 scrollbar_arrow_button_painters_), | |
| 152 gc, rect); | |
| 153 | |
| 154 // Aura-win uses slightly different arrow colors. | 142 // Aura-win uses slightly different arrow colors. |
| 155 SkColor arrow_color = GetArrowColor(state); | 143 SkColor arrow_color = gfx::kPlaceholderColor; |
| 156 switch (state) { | 144 switch (state) { |
| 145 case kDisabled: | |
| 146 arrow_color = GetArrowColor(state); | |
| 147 break; | |
| 157 case kHovered: | 148 case kHovered: |
| 149 bg_color = SkColorSetRGB(0xD2, 0xD2, 0xD2); | |
| 150 // Fall through. | |
| 158 case kNormal: | 151 case kNormal: |
| 159 arrow_color = SkColorSetRGB(0x50, 0x50, 0x50); | 152 arrow_color = SkColorSetRGB(0x50, 0x50, 0x50); |
| 160 break; | 153 break; |
| 161 case kPressed: | 154 case kPressed: |
| 155 bg_color = SkColorSetRGB(0x78, 0x78, 0x78); | |
| 162 arrow_color = SK_ColorWHITE; | 156 arrow_color = SK_ColorWHITE; |
| 163 default: | 157 break; |
| 158 case kNumStates: | |
| 164 break; | 159 break; |
|
sadrul
2016/01/12 21:57:45
I was going to suggest a NOTREACHED() here, but I
| |
| 165 } | 160 } |
| 166 PaintArrow(gc, rect, direction, arrow_color); | 161 DCHECK_NE(arrow_color, gfx::kPlaceholderColor); |
| 162 | |
| 163 SkPaint paint; | |
| 164 paint.setColor(bg_color); | |
| 165 canvas->drawIRect(gfx::RectToSkIRect(rect), paint); | |
| 166 | |
| 167 PaintArrow(canvas, rect, direction, arrow_color); | |
| 167 } | 168 } |
| 168 | 169 |
| 169 void NativeThemeAura::PaintScrollbarTrack( | 170 void NativeThemeAura::PaintScrollbarTrack( |
| 170 SkCanvas* sk_canvas, | 171 SkCanvas* canvas, |
| 171 Part part, | 172 Part part, |
| 172 State state, | 173 State state, |
| 173 const ScrollbarTrackExtraParams& extra_params, | 174 const ScrollbarTrackExtraParams& extra_params, |
| 174 const gfx::Rect& rect) const { | 175 const gfx::Rect& rect) const { |
| 175 // Overlay Scrollbar should never paint a scrollbar track. | 176 // Overlay Scrollbar should never paint a scrollbar track. |
| 176 DCHECK(!IsOverlayScrollbarEnabled()); | 177 DCHECK(!IsOverlayScrollbarEnabled()); |
| 177 if (!scrollbar_track_painter_) | 178 SkPaint paint; |
| 178 scrollbar_track_painter_ = CreateNineImagePainter(kScrollbarTrackImages); | 179 paint.setColor(kTrackColor); |
| 179 PaintPainter(scrollbar_track_painter_.get(), sk_canvas, rect); | 180 canvas->drawIRect(gfx::RectToSkIRect(rect), paint); |
| 180 } | 181 } |
| 181 | 182 |
| 182 void NativeThemeAura::PaintScrollbarThumb(SkCanvas* sk_canvas, | 183 void NativeThemeAura::PaintScrollbarThumb(SkCanvas* canvas, |
| 183 Part part, | 184 Part part, |
| 184 State state, | 185 State state, |
| 185 const gfx::Rect& rect) const { | 186 const gfx::Rect& rect) const { |
| 186 gfx::Rect thumb_rect(rect); | 187 // Do not paint if state is disabled. |
| 187 if (IsOverlayScrollbarEnabled()) { | 188 if (state == kDisabled) |
| 188 // Overlay scrollbar has no track, just paint thumb directly. | 189 return; |
| 189 // Do not paint if state is disabled. | |
| 190 if (state == kDisabled) | |
| 191 return; | |
| 192 | 190 |
| 193 if (!scrollbar_overlay_thumb_painter_) { | 191 PaintScrollbarThumbStateTransition(canvas, part, state, state, 1.0, rect); |
| 194 scrollbar_overlay_thumb_painter_ = | |
| 195 CreateDualPainter(kScrollbarOverlayThumbFillImages, | |
| 196 kScrollbarOverlayThumbFillAlphas, | |
| 197 kScrollbarOverlayThumbStrokeImages, | |
| 198 kScrollbarOverlayThumbStrokeAlphas); | |
| 199 } | |
| 200 | |
| 201 PaintDualPainter( | |
| 202 scrollbar_overlay_thumb_painter_.get(), sk_canvas, thumb_rect, state); | |
| 203 return; | |
| 204 } | |
| 205 // If there are no scrollbuttons then provide some padding so that thumb | |
| 206 // doesn't touch the top of the track. | |
| 207 const int extra_padding = (scrollbar_button_length() == 0) ? 2 : 0; | |
| 208 if (part == NativeTheme::kScrollbarVerticalThumb) | |
| 209 thumb_rect.Inset(2, extra_padding, 2, extra_padding); | |
| 210 else | |
| 211 thumb_rect.Inset(extra_padding, 2, extra_padding, 2); | |
| 212 PaintPainter(GetOrCreatePainter( | |
| 213 kScrollbarThumbImages, state, scrollbar_thumb_painters_), | |
| 214 sk_canvas, | |
| 215 thumb_rect); | |
| 216 } | 192 } |
| 217 | 193 |
| 218 void NativeThemeAura::PaintScrollbarThumbStateTransition( | 194 void NativeThemeAura::PaintScrollbarThumbStateTransition( |
| 219 SkCanvas* canvas, | 195 SkCanvas* canvas, |
| 220 State startState, | 196 Part part, |
| 221 State endState, | 197 State start_state, |
| 198 State end_state, | |
| 222 double progress, | 199 double progress, |
| 223 const gfx::Rect& rect) const { | 200 const gfx::Rect& rect) const { |
| 224 // Only Overlay scrollbars should have state transition animation. | 201 gfx::Rect thumb_rect(rect); |
| 225 DCHECK(IsOverlayScrollbarEnabled()); | 202 if (IsOverlayScrollbarEnabled()) { |
| 226 if (!scrollbar_overlay_thumb_painter_) { | 203 // In overlay mode, draw a stroke (border). |
| 227 scrollbar_overlay_thumb_painter_ = | 204 const int kStrokeWidth = 1; |
| 228 CreateDualPainter(kScrollbarOverlayThumbFillImages, | 205 SkAlpha stroke_alpha = gfx::Tween::IntValueBetween( |
| 229 kScrollbarOverlayThumbFillAlphas, | 206 progress, ThumbStrokeAlphaForState(start_state), |
| 230 kScrollbarOverlayThumbStrokeImages, | 207 ThumbStrokeAlphaForState(end_state)); |
| 231 kScrollbarOverlayThumbStrokeAlphas); | 208 SkPaint paint; |
| 209 paint.setColor(SkColorSetA(SK_ColorWHITE, stroke_alpha)); | |
| 210 paint.setStyle(SkPaint::kStroke_Style); | |
| 211 paint.setStrokeWidth(kStrokeWidth); | |
| 212 canvas->drawIRect(gfx::RectToSkIRect(thumb_rect), paint); | |
| 213 | |
| 214 thumb_rect.Inset(kStrokeWidth, kStrokeWidth, kStrokeWidth, kStrokeWidth); | |
| 215 } else { | |
| 216 // If there are no scrollbuttons then provide some padding so that the thumb | |
| 217 // doesn't touch the top of the track. | |
| 218 const int kThumbPadding = 2; | |
| 219 const int extra_padding = | |
| 220 (scrollbar_button_length() == 0) ? kThumbPadding : 0; | |
| 221 if (part == NativeTheme::kScrollbarVerticalThumb) | |
| 222 thumb_rect.Inset(kThumbPadding, extra_padding); | |
| 223 else | |
| 224 thumb_rect.Inset(extra_padding, kThumbPadding); | |
| 232 } | 225 } |
| 233 | 226 |
| 234 PaintDualPainterTransition(scrollbar_overlay_thumb_painter_.get(), | 227 SkPaint paint; |
| 235 canvas, | 228 SkAlpha alpha = gfx::Tween::IntValueBetween( |
| 236 rect, | 229 progress, ThumbAlphaForState(start_state), ThumbAlphaForState(end_state)); |
| 237 startState, | 230 paint.setColor(SkColorSetA(SK_ColorBLACK, alpha)); |
| 238 endState, | 231 canvas->drawIRect(gfx::RectToSkIRect(thumb_rect), paint); |
| 239 progress); | |
| 240 } | 232 } |
| 241 | 233 |
| 242 void NativeThemeAura::PaintScrollbarCorner(SkCanvas* canvas, | 234 void NativeThemeAura::PaintScrollbarCorner(SkCanvas* canvas, |
| 243 State state, | 235 State state, |
| 244 const gfx::Rect& rect) const { | 236 const gfx::Rect& rect) const { |
| 245 // Overlay Scrollbar should never paint a scrollbar corner. | 237 // Overlay Scrollbar should never paint a scrollbar corner. |
| 246 DCHECK(!IsOverlayScrollbarEnabled()); | 238 DCHECK(!IsOverlayScrollbarEnabled()); |
| 247 SkPaint paint; | 239 SkPaint paint; |
| 248 paint.setColor(SkColorSetRGB(0xF1, 0xF1, 0xF1)); | 240 paint.setColor(SkColorSetRGB(0xDC, 0xDC, 0xDC)); |
| 249 paint.setStyle(SkPaint::kFill_Style); | |
| 250 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | |
| 251 canvas->drawIRect(RectToSkIRect(rect), paint); | 241 canvas->drawIRect(RectToSkIRect(rect), paint); |
| 252 } | 242 } |
| 253 | 243 |
| 254 NineImagePainter* NativeThemeAura::GetOrCreatePainter( | |
| 255 const int images[kNumStates][9], | |
| 256 State state, | |
| 257 scoped_ptr<NineImagePainter> painters[kNumStates]) const { | |
| 258 if (painters[state]) | |
| 259 return painters[state].get(); | |
| 260 if (images[state][0] == 0) { | |
| 261 // Must always provide normal state images. | |
| 262 DCHECK_NE(kNormal, state); | |
| 263 return GetOrCreatePainter(images, kNormal, painters); | |
| 264 } | |
| 265 painters[state] = CreateNineImagePainter(images[state]); | |
| 266 return painters[state].get(); | |
| 267 } | |
| 268 | |
| 269 void NativeThemeAura::PaintPainter(NineImagePainter* painter, | |
| 270 SkCanvas* sk_canvas, | |
| 271 const gfx::Rect& rect) const { | |
| 272 DCHECK(painter); | |
| 273 scoped_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(sk_canvas)); | |
| 274 painter->Paint(canvas.get(), rect); | |
| 275 } | |
| 276 | |
| 277 scoped_ptr<NativeThemeAura::DualPainter> NativeThemeAura::CreateDualPainter( | |
| 278 const int fill_image_ids[9], | |
| 279 const uint8_t fill_alphas[kNumStates], | |
| 280 const int stroke_image_ids[9], | |
| 281 const uint8_t stroke_alphas[kNumStates]) const { | |
| 282 scoped_ptr<NativeThemeAura::DualPainter> dual_painter( | |
| 283 new NativeThemeAura::DualPainter(CreateNineImagePainter(fill_image_ids), | |
| 284 fill_alphas, | |
| 285 CreateNineImagePainter(stroke_image_ids), | |
| 286 stroke_alphas)); | |
| 287 return dual_painter; | |
| 288 } | |
| 289 | |
| 290 void NativeThemeAura::PaintDualPainter( | |
| 291 NativeThemeAura::DualPainter* dual_painter, | |
| 292 SkCanvas* sk_canvas, | |
| 293 const gfx::Rect& rect, | |
| 294 State state) const { | |
| 295 DCHECK(dual_painter); | |
| 296 scoped_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(sk_canvas)); | |
| 297 dual_painter->fill_painter->Paint( | |
| 298 canvas.get(), rect, dual_painter->fill_alphas[state]); | |
| 299 dual_painter->stroke_painter->Paint( | |
| 300 canvas.get(), rect, dual_painter->stroke_alphas[state]); | |
| 301 } | |
| 302 | |
| 303 void NativeThemeAura::PaintDualPainterTransition( | |
| 304 NativeThemeAura::DualPainter* dual_painter, | |
| 305 SkCanvas* sk_canvas, | |
| 306 const gfx::Rect& rect, | |
| 307 State startState, | |
| 308 State endState, | |
| 309 double progress) const { | |
| 310 DCHECK(dual_painter); | |
| 311 scoped_ptr<gfx::Canvas> canvas(CommonThemeCreateCanvas(sk_canvas)); | |
| 312 uint8_t fill_alpha = dual_painter->fill_alphas[startState] + | |
| 313 (dual_painter->fill_alphas[endState] - | |
| 314 dual_painter->fill_alphas[startState]) * | |
| 315 progress; | |
| 316 uint8_t stroke_alpha = dual_painter->stroke_alphas[startState] + | |
| 317 (dual_painter->stroke_alphas[endState] - | |
| 318 dual_painter->stroke_alphas[startState]) * | |
| 319 progress; | |
| 320 | |
| 321 dual_painter->fill_painter->Paint(canvas.get(), rect, fill_alpha); | |
| 322 dual_painter->stroke_painter->Paint(canvas.get(), rect, stroke_alpha); | |
| 323 } | |
| 324 | |
| 325 NativeThemeAura::DualPainter::DualPainter( | |
| 326 scoped_ptr<NineImagePainter> fill_painter, | |
| 327 const uint8_t fill_alphas[kNumStates], | |
| 328 scoped_ptr<NineImagePainter> stroke_painter, | |
| 329 const uint8_t stroke_alphas[kNumStates]) | |
| 330 : fill_painter(std::move(fill_painter)), | |
| 331 fill_alphas(fill_alphas), | |
| 332 stroke_painter(std::move(stroke_painter)), | |
| 333 stroke_alphas(stroke_alphas) {} | |
| 334 | |
| 335 NativeThemeAura::DualPainter::~DualPainter() {} | |
| 336 | |
| 337 } // namespace ui | 244 } // namespace ui |
| OLD | NEW |