| 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/views/controls/button/label_button_border.h" | 5 #include "ui/views/controls/button/label_button_border.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "grit/ui_resources.h" | 9 #include "grit/ui_resources.h" |
| 10 #include "ui/base/animation/animation.h" | 10 #include "ui/base/animation/animation.h" |
| 11 #include "ui/base/resource/resource_bundle.h" | 11 #include "ui/base/resource/resource_bundle.h" |
| 12 #include "ui/gfx/canvas.h" | 12 #include "ui/gfx/canvas.h" |
| 13 #include "ui/views/controls/button/label_button.h" | 13 #include "ui/views/controls/button/label_button.h" |
| 14 #include "ui/views/native_theme_delegate.h" |
| 14 | 15 |
| 15 namespace { | 16 namespace { |
| 16 | 17 |
| 17 // Preferred padding between content and edge. | 18 // Preferred padding between content and edge. |
| 18 static const int kPreferredPaddingHorizontal = 6; | 19 static const int kPreferredPaddingHorizontal = 6; |
| 19 static const int kPreferredPaddingVertical = 5; | 20 static const int kPreferredPaddingVertical = 5; |
| 20 | 21 |
| 21 // Preferred padding between content and edge for NativeTheme border. | 22 // Preferred padding between content and edge for NativeTheme border. |
| 22 static const int kPreferredNativeThemePaddingHorizontal = 12; | 23 static const int kPreferredNativeThemePaddingHorizontal = 12; |
| 23 static const int kPreferredNativeThemePaddingVertical = 5; | 24 static const int kPreferredNativeThemePaddingVertical = 5; |
| 24 | 25 |
| 25 const int kHoverImageSet[] = { | |
| 26 IDR_TEXTBUTTON_HOVER_TOP_LEFT, | |
| 27 IDR_TEXTBUTTON_HOVER_TOP, | |
| 28 IDR_TEXTBUTTON_HOVER_TOP_RIGHT, | |
| 29 IDR_TEXTBUTTON_HOVER_LEFT, | |
| 30 IDR_TEXTBUTTON_HOVER_CENTER, | |
| 31 IDR_TEXTBUTTON_HOVER_RIGHT, | |
| 32 IDR_TEXTBUTTON_HOVER_BOTTOM_LEFT, | |
| 33 IDR_TEXTBUTTON_HOVER_BOTTOM, | |
| 34 IDR_TEXTBUTTON_HOVER_BOTTOM_RIGHT, | |
| 35 }; | |
| 36 | |
| 37 const int kPressedImageSet[] = { | |
| 38 IDR_TEXTBUTTON_PRESSED_TOP_LEFT, | |
| 39 IDR_TEXTBUTTON_PRESSED_TOP, | |
| 40 IDR_TEXTBUTTON_PRESSED_TOP_RIGHT, | |
| 41 IDR_TEXTBUTTON_PRESSED_LEFT, | |
| 42 IDR_TEXTBUTTON_PRESSED_CENTER, | |
| 43 IDR_TEXTBUTTON_PRESSED_RIGHT, | |
| 44 IDR_TEXTBUTTON_PRESSED_BOTTOM_LEFT, | |
| 45 IDR_TEXTBUTTON_PRESSED_BOTTOM, | |
| 46 IDR_TEXTBUTTON_PRESSED_BOTTOM_RIGHT, | |
| 47 }; | |
| 48 | |
| 49 } // namespace | 26 } // namespace |
| 50 | 27 |
| 51 namespace views { | 28 namespace views { |
| 52 | 29 |
| 53 LabelButtonBorder::LabelButtonBorder(NativeThemeDelegate* delegate) | 30 LabelButtonBorder::LabelButtonBorder() : native_theme_(false) { |
| 54 : native_theme_delegate_(delegate), | 31 SetImages(CustomButton::BS_HOT, BorderImages(BorderImages::kHot)); |
| 55 native_theme_(false) { | 32 SetImages(CustomButton::BS_PUSHED, BorderImages(BorderImages::kPushed)); |
| 56 SetImages(CustomButton::BS_HOT, BorderImages(kHoverImageSet)); | |
| 57 SetImages(CustomButton::BS_PUSHED, BorderImages(kPressedImageSet)); | |
| 58 } | 33 } |
| 59 | 34 |
| 60 LabelButtonBorder::~LabelButtonBorder() {} | 35 LabelButtonBorder::~LabelButtonBorder() {} |
| 61 | 36 |
| 62 void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) const { | 37 void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) const { |
| 63 const CustomButton* button = static_cast<const CustomButton*>(&view); | 38 const LabelButton* button = static_cast<const LabelButton*>(&view); |
| 64 if (native_theme()) { | 39 if (native_theme()) |
| 65 PaintNativeTheme(view, canvas); | 40 PaintNativeTheme(button, canvas); |
| 66 } else if (native_theme_delegate_->GetThemeAnimation() && | 41 else |
| 67 native_theme_delegate_->GetThemeAnimation()->is_animating()) { | 42 PaintImages(button, canvas); |
| 68 // TODO(msw): Crossfade between image sets; no-op for equivalent images. | |
| 69 canvas->SaveLayerAlpha(static_cast<uint8>(native_theme_delegate_-> | |
| 70 GetThemeAnimation()->CurrentValueBetween(0, 255))); | |
| 71 canvas->DrawColor(SkColorSetARGB(0x00, 0xFF, 0xFF, 0xFF), | |
| 72 SkXfermode::kClear_Mode); | |
| 73 PaintImages(view, canvas, button->state()); | |
| 74 canvas->Restore(); | |
| 75 } else { | |
| 76 PaintImages(view, canvas, button->state()); | |
| 77 } | |
| 78 } | 43 } |
| 79 | 44 |
| 80 void LabelButtonBorder::GetInsets(gfx::Insets* insets) const { | 45 void LabelButtonBorder::GetInsets(gfx::Insets* insets) const { |
| 81 if (native_theme()) { | 46 if (native_theme()) { |
| 82 insets->Set(kPreferredNativeThemePaddingVertical, | 47 insets->Set(kPreferredNativeThemePaddingVertical, |
| 83 kPreferredNativeThemePaddingHorizontal, | 48 kPreferredNativeThemePaddingHorizontal, |
| 84 kPreferredNativeThemePaddingVertical, | 49 kPreferredNativeThemePaddingVertical, |
| 85 kPreferredNativeThemePaddingHorizontal); | 50 kPreferredNativeThemePaddingHorizontal); |
| 86 } else { | 51 } else { |
| 87 insets->Set(kPreferredPaddingVertical, kPreferredPaddingHorizontal, | 52 insets->Set(kPreferredPaddingVertical, kPreferredPaddingHorizontal, |
| 88 kPreferredPaddingVertical, kPreferredPaddingHorizontal); | 53 kPreferredPaddingVertical, kPreferredPaddingHorizontal); |
| 89 } | 54 } |
| 90 } | 55 } |
| 91 | 56 |
| 92 LabelButtonBorder::BorderImages::BorderImages() {} | |
| 93 | |
| 94 LabelButtonBorder::BorderImages::~BorderImages() {} | |
| 95 | |
| 96 LabelButtonBorder::BorderImages::BorderImages(const int image_ids[]) { | |
| 97 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 98 top_left = *rb.GetImageSkiaNamed(image_ids[0]); | |
| 99 top = *rb.GetImageSkiaNamed(image_ids[1]); | |
| 100 top_right = *rb.GetImageSkiaNamed(image_ids[2]); | |
| 101 left = *rb.GetImageSkiaNamed(image_ids[3]); | |
| 102 center = *rb.GetImageSkiaNamed(image_ids[4]); | |
| 103 right = *rb.GetImageSkiaNamed(image_ids[5]); | |
| 104 bottom_left = *rb.GetImageSkiaNamed(image_ids[6]); | |
| 105 bottom = *rb.GetImageSkiaNamed(image_ids[7]); | |
| 106 bottom_right = *rb.GetImageSkiaNamed(image_ids[8]); | |
| 107 } | |
| 108 | |
| 109 void LabelButtonBorder::SetImages(CustomButton::ButtonState state, | 57 void LabelButtonBorder::SetImages(CustomButton::ButtonState state, |
| 110 const BorderImages& set) { | 58 const BorderImages& set) { |
| 111 images_[state] = set; | 59 images_[state] = set; |
| 112 } | 60 } |
| 113 | 61 |
| 114 void LabelButtonBorder::PaintImages(const View& view, | 62 void LabelButtonBorder::PaintImages(const LabelButton* button, |
| 115 gfx::Canvas* canvas, | 63 gfx::Canvas* canvas) const { |
| 116 CustomButton::ButtonState state) const { | 64 const BorderImages& set = images_[button->state()]; |
| 117 const BorderImages& set = images_[state]; | 65 if (!set.top_left.isNull()) { |
| 118 if (set.top_left.isNull()) | 66 const ui::Animation* animation = |
| 119 return; | 67 static_cast<const NativeThemeDelegate*>(button)->GetThemeAnimation(); |
| 120 | 68 if (animation && animation->is_animating()) { |
| 121 const int width = view.bounds().width(); | 69 // TODO(msw): Crossfade between image sets; no-op for equivalent images. |
| 122 const int height = view.bounds().height(); | 70 const int alpha = animation->CurrentValueBetween(0, 255); |
| 123 const int tl_width = set.top_left.width(); | 71 canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); |
| 124 const int tl_height = set.top_left.height(); | 72 set.Paint(button->GetLocalBounds(), canvas); |
| 125 const int t_height = set.top.height(); | 73 canvas->Restore(); |
| 126 const int tr_height = set.top_right.height(); | 74 } else { |
| 127 const int l_width = set.left.width(); | 75 set.Paint(button->GetLocalBounds(), canvas); |
| 128 const int r_width = set.right.width(); | 76 } |
| 129 const int bl_width = set.bottom_left.width(); | 77 } |
| 130 const int bl_height = set.bottom_left.height(); | |
| 131 const int b_height = set.bottom.height(); | |
| 132 const int br_width = set.bottom_right.width(); | |
| 133 const int br_height = set.bottom_right.height(); | |
| 134 | |
| 135 canvas->DrawImageInt(set.top_left, 0, 0); | |
| 136 canvas->DrawImageInt(set.top, 0, 0, set.top.width(), t_height, tl_width, 0, | |
| 137 width - tl_width - set.top_right.width(), t_height, false); | |
| 138 canvas->DrawImageInt(set.top_right, width - set.top_right.width(), 0); | |
| 139 canvas->DrawImageInt(set.left, 0, 0, l_width, set.left.height(), 0, | |
| 140 tl_height, tl_width, height - tl_height - bl_height, false); | |
| 141 canvas->DrawImageInt(set.center, 0, 0, set.center.width(), | |
| 142 set.center.height(), l_width, t_height, width - l_width - r_width, | |
| 143 height - t_height - b_height, false); | |
| 144 canvas->DrawImageInt(set.right, 0, 0, r_width, set.right.height(), | |
| 145 width - r_width, tr_height, r_width, | |
| 146 height - tr_height - br_height, false); | |
| 147 canvas->DrawImageInt(set.bottom_left, 0, height - bl_height); | |
| 148 canvas->DrawImageInt(set.bottom, 0, 0, set.bottom.width(), b_height, | |
| 149 bl_width, height - b_height, | |
| 150 width - bl_width - br_width, b_height, false); | |
| 151 canvas->DrawImageInt(set.bottom_right, width - br_width, | |
| 152 height - br_height); | |
| 153 } | 78 } |
| 154 | 79 |
| 155 void LabelButtonBorder::PaintNativeTheme(const View& view, | 80 void LabelButtonBorder::PaintNativeTheme(const LabelButton* button, |
| 156 gfx::Canvas* canvas) const { | 81 gfx::Canvas* canvas) const { |
| 157 const ui::NativeTheme* theme = ui::NativeTheme::instance(); | 82 const NativeThemeDelegate* native_theme_delegate = |
| 158 ui::NativeTheme::Part part = native_theme_delegate_->GetThemePart(); | 83 static_cast<const NativeThemeDelegate*>(button); |
| 159 gfx::Rect rect(native_theme_delegate_->GetThemePaintRect()); | 84 ui::NativeTheme::Part part = native_theme_delegate->GetThemePart(); |
| 85 gfx::Rect rect(native_theme_delegate->GetThemePaintRect()); |
| 160 | 86 |
| 161 ui::NativeTheme::State state; | 87 ui::NativeTheme::State state; |
| 162 ui::NativeTheme::ExtraParams extra; | 88 ui::NativeTheme::ExtraParams extra; |
| 163 const ui::Animation* animation = native_theme_delegate_->GetThemeAnimation(); | 89 const ui::NativeTheme* theme = ui::NativeTheme::instance(); |
| 90 const ui::Animation* animation = native_theme_delegate->GetThemeAnimation(); |
| 164 if (animation && animation->is_animating()) { | 91 if (animation && animation->is_animating()) { |
| 165 // Paint the background state. | 92 // Paint the background state. |
| 166 state = native_theme_delegate_->GetBackgroundThemeState(&extra); | 93 state = native_theme_delegate->GetBackgroundThemeState(&extra); |
| 167 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); | 94 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); |
| 168 | 95 |
| 169 // Composite the foreground state above the background state. | 96 // Composite the foreground state above the background state. |
| 170 state = native_theme_delegate_->GetForegroundThemeState(&extra); | 97 state = native_theme_delegate->GetForegroundThemeState(&extra); |
| 171 const int alpha = animation->CurrentValueBetween(0, 255); | 98 const int alpha = animation->CurrentValueBetween(0, 255); |
| 172 canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); | 99 canvas->SaveLayerAlpha(static_cast<uint8>(alpha)); |
| 173 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); | 100 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); |
| 174 canvas->Restore(); | 101 canvas->Restore(); |
| 175 } else { | 102 } else { |
| 176 state = native_theme_delegate_->GetThemeState(&extra); | 103 state = native_theme_delegate->GetThemeState(&extra); |
| 177 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); | 104 theme->Paint(canvas->sk_canvas(), part, state, rect, extra); |
| 178 } | 105 } |
| 179 | 106 |
| 180 // Draw the Views focus border for the native theme style. | 107 // Draw the Views focus border for the native theme style. |
| 181 if (view.focus_border() && extra.button.is_focused) | 108 if (button->focus_border() && extra.button.is_focused) |
| 182 view.focus_border()->Paint(view, canvas); | 109 button->focus_border()->Paint(*button, canvas); |
| 183 } | 110 } |
| 184 | 111 |
| 185 } // namespace views | 112 } // namespace views |
| OLD | NEW |