label_button_border.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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/views/controls/button/label_button_border.h" 6 7#include "base/logging.h" 8#include "grit/ui_resources.h" 9#include "ui/base/animation/animation.h" 10#include "ui/gfx/canvas.h" 11#include "ui/gfx/rect.h" 12#include "ui/gfx/sys_color_change_listener.h" 13#include "ui/native_theme/native_theme.h" 14#include "ui/views/controls/button/label_button.h" 15#include "ui/views/native_theme_delegate.h" 16 17namespace views { 18 19namespace { 20 21// The button image IDs and focused images IDs used in lieu of a focus border. 22const int kNormalImages[] = IMAGE_GRID(IDR_BUTTON_NORMAL); 23const int kHoveredImages[] = IMAGE_GRID(IDR_BUTTON_HOVER); 24const int kPressedImages[] = IMAGE_GRID(IDR_BUTTON_PRESSED); 25const int kDisabledImages[] = IMAGE_GRID(IDR_BUTTON_DISABLED); 26const int kFocusedNormalImages[] = IMAGE_GRID(IDR_BUTTON_FOCUSED_NORMAL); 27const int kFocusedHoveredImages[] = IMAGE_GRID(IDR_BUTTON_FOCUSED_HOVER); 28const int kFocusedPressedImages[] = IMAGE_GRID(IDR_BUTTON_FOCUSED_PRESSED); 29 30// The text-button hot and pushed image IDs; normal is unadorned by default. 31const int kTextHoveredImages[] = IMAGE_GRID(IDR_TEXTBUTTON_HOVER); 32const int kTextPressedImages[] = IMAGE_GRID(IDR_TEXTBUTTON_PRESSED); 33 34Button::ButtonState GetButtonState(ui::NativeTheme::State state) { 35 switch (state) { 36 case ui::NativeTheme::kDisabled: return Button::STATE_DISABLED; 37 case ui::NativeTheme::kHovered: return Button::STATE_HOVERED; 38 case ui::NativeTheme::kNormal: return Button::STATE_NORMAL; 39 case ui::NativeTheme::kPressed: return Button::STATE_PRESSED; 40 case ui::NativeTheme::kMaxState: NOTREACHED() << "Unknown state: " << state; 41 } 42 return Button::STATE_NORMAL; 43} 44 45// A helper function to paint the native theme or images as appropriate. 46void PaintHelper(LabelButtonBorder* border, 47 gfx::Canvas* canvas, 48 const ui::NativeTheme* theme, 49 ui::NativeTheme::Part part, 50 ui::NativeTheme::State state, 51 const gfx::Rect& rect, 52 const ui::NativeTheme::ExtraParams& extra) { 53 if (border->style() == Button::STYLE_NATIVE_TEXTBUTTON) { 54 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); 55 } else { 56 Painter* painter = 57 border->GetPainter(extra.button.is_focused, GetButtonState(state)); 58 // Paint any corresponding unfocused painter if there is no focused painter. 59 if (!painter && extra.button.is_focused) 60 painter = border->GetPainter(false, GetButtonState(state)); 61 if (painter) 62 painter->Paint(canvas, rect.size()); 63 } 64} 65 66} // namespace 67 68LabelButtonBorder::LabelButtonBorder(Button::ButtonStyle style) 69 : style_(style) { 70 if (style == Button::STYLE_BUTTON) { 71 set_insets(gfx::Insets(8, 13, 8, 13)); 72 SetPainter(false, Button::STATE_NORMAL, 73 Painter::CreateImageGridPainter(kNormalImages)); 74 SetPainter(false, Button::STATE_HOVERED, 75 Painter::CreateImageGridPainter(kHoveredImages)); 76 SetPainter(false, Button::STATE_PRESSED, 77 Painter::CreateImageGridPainter(kPressedImages)); 78 SetPainter(false, Button::STATE_DISABLED, 79 Painter::CreateImageGridPainter(kDisabledImages)); 80 SetPainter(true, Button::STATE_NORMAL, 81 Painter::CreateImageGridPainter(kFocusedNormalImages)); 82 SetPainter(true, Button::STATE_HOVERED, 83 Painter::CreateImageGridPainter(kFocusedHoveredImages)); 84 SetPainter(true, Button::STATE_PRESSED, 85 Painter::CreateImageGridPainter(kFocusedPressedImages)); 86 SetPainter(true, Button::STATE_DISABLED, 87 Painter::CreateImageGridPainter(kDisabledImages)); 88 } else if (style == Button::STYLE_TEXTBUTTON) { 89 set_insets(gfx::Insets(5, 6, 5, 6)); 90 SetPainter(false, Button::STATE_HOVERED, 91 Painter::CreateImageGridPainter(kTextHoveredImages)); 92 SetPainter(false, Button::STATE_PRESSED, 93 Painter::CreateImageGridPainter(kTextPressedImages)); 94 } else if (style == Button::STYLE_NATIVE_TEXTBUTTON) { 95 set_insets(gfx::Insets(5, 12, 5, 12)); 96 } 97} 98 99LabelButtonBorder::~LabelButtonBorder() {} 100 101void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) { 102 const NativeThemeDelegate* native_theme_delegate = 103 static_cast<const LabelButton*>(&view); 104 ui::NativeTheme::Part part = native_theme_delegate->GetThemePart(); 105 gfx::Rect rect(native_theme_delegate->GetThemePaintRect()); 106 ui::NativeTheme::ExtraParams extra; 107 const ui::NativeTheme* theme = view.GetNativeTheme(); 108 const ui::Animation* animation = native_theme_delegate->GetThemeAnimation(); 109 ui::NativeTheme::State state = native_theme_delegate->GetThemeState(&extra); 110 111 if (animation && animation->is_animating()) { 112 // Composite the background and foreground painters during state animations. 113 int alpha = animation->CurrentValueBetween(0, 0xff); 114 state = native_theme_delegate->GetBackgroundThemeState(&extra); 115 canvas->SaveLayerAlpha(static_cast<uint8>(0xff - alpha)); 116 PaintHelper(this, canvas, theme, part, state, rect, extra); 117 canvas->Restore(); 118 119 state = native_theme_delegate->GetForegroundThemeState(&extra); 120 canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); 121 PaintHelper(this, canvas, theme, part, state, rect, extra); 122 canvas->Restore(); 123 } else { 124 PaintHelper(this, canvas, theme, part, state, rect, extra); 125 } 126 127 // For inverted color schemes, draw a solid fill with the button color. 128 if (gfx::IsInvertedColorScheme()) { 129 rect.Inset(insets_); 130 canvas->FillRect(rect, extra.button.background_color); 131 } 132 133 // Draw the Views focus border for the native theme style. 134 if (style() == Button::STYLE_NATIVE_TEXTBUTTON && 135 view.focus_border() && extra.button.is_focused) 136 view.focus_border()->Paint(view, canvas); 137} 138 139gfx::Insets LabelButtonBorder::GetInsets() const { 140 return insets_; 141} 142 143Painter* LabelButtonBorder::GetPainter(bool focused, 144 Button::ButtonState state) { 145 return painters_[focused ? 1 : 0][state].get(); 146} 147 148void LabelButtonBorder::SetPainter(bool focused, 149 Button::ButtonState state, 150 Painter* painter) { 151 painters_[focused ? 1 : 0][state].reset(painter); 152} 153 154} // namespace views 155