| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/native_theme/native_theme_aura.h" |
| |
| #include <limits> |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "build/build_config.h" |
| #include "ui/base/layout.h" |
| #include "ui/base/material_design/material_design_controller.h" |
| #include "ui/gfx/animation/tween.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/color_palette.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/path.h" |
| #include "ui/gfx/skia_util.h" |
| #include "ui/native_theme/common_theme.h" |
| #include "ui/native_theme/native_theme_switches.h" |
| |
| namespace ui { |
| |
| namespace { |
| |
| SkAlpha ThumbAlphaForState(NativeTheme::State state) { |
| bool overlay = IsOverlayScrollbarEnabled(); |
| switch (state) { |
| case NativeTheme::kDisabled: |
| return 0x00; |
| case NativeTheme::kHovered: |
| return overlay ? 0xB2 : 0x4D; |
| case NativeTheme::kNormal: |
| return overlay ? 0x8C : 0x33; |
| case NativeTheme::kPressed: |
| return overlay ? 0xB2 : 0x80; |
| case NativeTheme::kNumStates: |
| break; |
| } |
| |
| NOTREACHED(); |
| return 0xFF; |
| } |
| |
| SkAlpha ThumbStrokeAlphaForState(NativeTheme::State state) { |
| DCHECK(IsOverlayScrollbarEnabled()); |
| switch (state) { |
| case NativeTheme::kDisabled: |
| return 0x00; |
| case NativeTheme::kHovered: |
| case NativeTheme::kPressed: |
| return 0x33; |
| case NativeTheme::kNormal: |
| return 0x26; |
| case NativeTheme::kNumStates: |
| break; |
| } |
| |
| NOTREACHED(); |
| return 0xFF; |
| } |
| |
| const SkColor kTrackColor = SkColorSetRGB(0xF1, 0xF1, 0xF1); |
| |
| } // namespace |
| |
| #if !defined(OS_WIN) |
| // static |
| NativeTheme* NativeTheme::GetInstanceForWeb() { |
| return NativeThemeAura::instance(); |
| } |
| |
| // static |
| NativeThemeAura* NativeThemeAura::instance() { |
| CR_DEFINE_STATIC_LOCAL(NativeThemeAura, s_native_theme, ()); |
| return &s_native_theme; |
| } |
| #endif |
| |
| NativeThemeAura::NativeThemeAura() { |
| // We don't draw scrollbar buttons. |
| #if defined(OS_CHROMEOS) |
| set_scrollbar_button_length(0); |
| #endif |
| |
| // Images and alphas declarations assume the following order. |
| static_assert(kDisabled == 0, "states unexpectedly changed"); |
| static_assert(kHovered == 1, "states unexpectedly changed"); |
| static_assert(kNormal == 2, "states unexpectedly changed"); |
| static_assert(kPressed == 3, "states unexpectedly changed"); |
| } |
| |
| NativeThemeAura::~NativeThemeAura() { |
| } |
| |
| // This implementation returns hardcoded colors. |
| SkColor NativeThemeAura::GetSystemColor(ColorId color_id) const { |
| return GetAuraColor(color_id, this); |
| } |
| |
| void NativeThemeAura::PaintMenuPopupBackground( |
| SkCanvas* canvas, |
| const gfx::Size& size, |
| const MenuBackgroundExtraParams& menu_background) const { |
| SkColor color = GetSystemColor(NativeTheme::kColorId_MenuBackgroundColor); |
| if (menu_background.corner_radius > 0) { |
| SkPaint paint; |
| paint.setStyle(SkPaint::kFill_Style); |
| paint.setFlags(SkPaint::kAntiAlias_Flag); |
| paint.setColor(color); |
| |
| gfx::Path path; |
| SkRect rect = SkRect::MakeWH(SkIntToScalar(size.width()), |
| SkIntToScalar(size.height())); |
| SkScalar radius = SkIntToScalar(menu_background.corner_radius); |
| SkScalar radii[8] = {radius, radius, radius, radius, |
| radius, radius, radius, radius}; |
| path.addRoundRect(rect, radii); |
| |
| canvas->drawPath(path, paint); |
| } else { |
| canvas->drawColor(color, SkXfermode::kSrc_Mode); |
| } |
| } |
| |
| void NativeThemeAura::PaintMenuItemBackground( |
| SkCanvas* canvas, |
| State state, |
| const gfx::Rect& rect, |
| const MenuListExtraParams& menu_list) const { |
| CommonThemePaintMenuItemBackground(canvas, state, rect); |
| } |
| |
| void NativeThemeAura::PaintArrowButton(SkCanvas* canvas, |
| const gfx::Rect& rect, |
| Part direction, |
| State state) const { |
| SkColor bg_color = kTrackColor; |
| // Aura-win uses slightly different arrow colors. |
| SkColor arrow_color = gfx::kPlaceholderColor; |
| switch (state) { |
| case kDisabled: |
| arrow_color = GetArrowColor(state); |
| break; |
| case kHovered: |
| bg_color = SkColorSetRGB(0xD2, 0xD2, 0xD2); |
| // Fall through. |
| case kNormal: |
| arrow_color = SkColorSetRGB(0x50, 0x50, 0x50); |
| break; |
| case kPressed: |
| bg_color = SkColorSetRGB(0x78, 0x78, 0x78); |
| arrow_color = SK_ColorWHITE; |
| break; |
| case kNumStates: |
| break; |
| } |
| DCHECK_NE(arrow_color, gfx::kPlaceholderColor); |
| |
| SkPaint paint; |
| paint.setColor(bg_color); |
| canvas->drawIRect(gfx::RectToSkIRect(rect), paint); |
| |
| PaintArrow(canvas, rect, direction, arrow_color); |
| } |
| |
| void NativeThemeAura::PaintScrollbarTrack( |
| SkCanvas* canvas, |
| Part part, |
| State state, |
| const ScrollbarTrackExtraParams& extra_params, |
| const gfx::Rect& rect) const { |
| // Overlay Scrollbar should never paint a scrollbar track. |
| DCHECK(!IsOverlayScrollbarEnabled()); |
| SkPaint paint; |
| paint.setColor(kTrackColor); |
| canvas->drawIRect(gfx::RectToSkIRect(rect), paint); |
| } |
| |
| void NativeThemeAura::PaintScrollbarThumb(SkCanvas* canvas, |
| Part part, |
| State state, |
| const gfx::Rect& rect) const { |
| // Do not paint if state is disabled. |
| if (state == kDisabled) |
| return; |
| |
| PaintScrollbarThumbStateTransition(canvas, part, state, state, 1.0, rect); |
| } |
| |
| void NativeThemeAura::PaintScrollbarThumbStateTransition( |
| SkCanvas* canvas, |
| Part part, |
| State start_state, |
| State end_state, |
| double progress, |
| const gfx::Rect& rect) const { |
| gfx::Rect thumb_rect(rect); |
| if (IsOverlayScrollbarEnabled()) { |
| // In overlay mode, draw a stroke (border). |
| const int kStrokeWidth = 1; |
| SkAlpha stroke_alpha = gfx::Tween::IntValueBetween( |
| progress, ThumbStrokeAlphaForState(start_state), |
| ThumbStrokeAlphaForState(end_state)); |
| SkPaint paint; |
| paint.setColor(SkColorSetA(SK_ColorWHITE, stroke_alpha)); |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setStrokeWidth(kStrokeWidth); |
| canvas->drawIRect(gfx::RectToSkIRect(thumb_rect), paint); |
| |
| thumb_rect.Inset(kStrokeWidth, kStrokeWidth, kStrokeWidth, kStrokeWidth); |
| } else { |
| // If there are no scrollbuttons then provide some padding so that the thumb |
| // doesn't touch the top of the track. |
| const int kThumbPadding = 2; |
| const int extra_padding = |
| (scrollbar_button_length() == 0) ? kThumbPadding : 0; |
| if (part == NativeTheme::kScrollbarVerticalThumb) |
| thumb_rect.Inset(kThumbPadding, extra_padding); |
| else |
| thumb_rect.Inset(extra_padding, kThumbPadding); |
| } |
| |
| SkPaint paint; |
| SkAlpha alpha = gfx::Tween::IntValueBetween( |
| progress, ThumbAlphaForState(start_state), ThumbAlphaForState(end_state)); |
| paint.setColor(SkColorSetA(SK_ColorBLACK, alpha)); |
| canvas->drawIRect(gfx::RectToSkIRect(thumb_rect), paint); |
| } |
| |
| void NativeThemeAura::PaintScrollbarCorner(SkCanvas* canvas, |
| State state, |
| const gfx::Rect& rect) const { |
| // Overlay Scrollbar should never paint a scrollbar corner. |
| DCHECK(!IsOverlayScrollbarEnabled()); |
| SkPaint paint; |
| paint.setColor(SkColorSetRGB(0xDC, 0xDC, 0xDC)); |
| canvas->drawIRect(RectToSkIRect(rect), paint); |
| } |
| |
| } // namespace ui |