Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/ui/views/profiles/new_avatar_button.h" | 5 #include "chrome/browser/ui/views/profiles/new_avatar_button.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
| 10 #include "chrome/app/vector_icons/vector_icons.h" | 10 #include "chrome/app/vector_icons/vector_icons.h" |
| 11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
| 12 #include "chrome/browser/profiles/profile_attributes_entry.h" | 12 #include "chrome/browser/profiles/profile_attributes_entry.h" |
| 13 #include "chrome/browser/profiles/profile_manager.h" | 13 #include "chrome/browser/profiles/profile_manager.h" |
| 14 #include "chrome/browser/profiles/profiles_state.h" | 14 #include "chrome/browser/profiles/profiles_state.h" |
| 15 #include "chrome/browser/themes/theme_properties.h" | |
| 15 #include "chrome/browser/ui/views/profiles/avatar_button_delegate.h" | 16 #include "chrome/browser/ui/views/profiles/avatar_button_delegate.h" |
| 16 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" | 17 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" |
| 17 #include "chrome/grit/theme_resources.h" | 18 #include "chrome/grit/theme_resources.h" |
| 18 #include "components/signin/core/common/profile_management_switches.h" | 19 #include "components/signin/core/common/profile_management_switches.h" |
| 19 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
| 21 #include "ui/base/theme_provider.h" | |
| 20 #include "ui/gfx/canvas.h" | 22 #include "ui/gfx/canvas.h" |
| 21 #include "ui/gfx/color_palette.h" | 23 #include "ui/gfx/color_palette.h" |
| 22 #include "ui/gfx/geometry/vector2d.h" | 24 #include "ui/gfx/geometry/vector2d.h" |
| 23 #include "ui/gfx/paint_vector_icon.h" | 25 #include "ui/gfx/paint_vector_icon.h" |
| 24 #include "ui/vector_icons/vector_icons.h" | 26 #include "ui/vector_icons/vector_icons.h" |
| 27 #include "ui/views/animation/ink_drop_mask.h" | |
| 25 #include "ui/views/border.h" | 28 #include "ui/views/border.h" |
| 26 #include "ui/views/controls/button/label_button_border.h" | 29 #include "ui/views/controls/button/label_button_border.h" |
| 27 #include "ui/views/painter.h" | 30 #include "ui/views/painter.h" |
| 28 | 31 |
| 29 #if defined(OS_WIN) | 32 #if defined(OS_WIN) |
| 30 #include "base/win/windows_version.h" | 33 #include "base/win/windows_version.h" |
| 31 #endif | 34 #endif |
| 32 | 35 |
| 33 namespace { | 36 namespace { |
| 34 | 37 |
| 38 // Insets between view bounds and the filled region for | |
| 39 // AvatarButtonThemedBorder. | |
| 40 static constexpr gfx::InsetsF kFillInsets(1); | |
| 41 | |
| 42 // Corner radius of the roundrect for AvatarButtonThemedBorder. | |
| 43 static constexpr float kCornerRadius = 1; | |
| 44 | |
| 45 // This class draws the border (and background) of the avatar button for | |
| 46 // "themed" browser windows, i.e. OpaqueBrowserFrameView. Currently it's only | |
| 47 // used on Linux as the shape specifically matches the Linux caption buttons. | |
| 48 // TODO(estade): make this look nice on Windows and use it there as well. | |
| 49 class AvatarButtonThemedBorder : public views::Border { | |
| 50 public: | |
| 51 AvatarButtonThemedBorder() {} | |
| 52 ~AvatarButtonThemedBorder() override {} | |
| 53 | |
| 54 void Paint(const views::View& view, gfx::Canvas* canvas) override { | |
| 55 gfx::RectF fill_bounds(view.GetLocalBounds()); | |
| 56 fill_bounds.Inset(kFillInsets); | |
| 57 cc::PaintFlags fill_flags; | |
| 58 fill_flags.setStyle(cc::PaintFlags::kFill_Style); | |
| 59 fill_flags.setColor(view.GetThemeProvider()->GetColor( | |
| 60 ThemeProperties::COLOR_BUTTON_BACKGROUND)); | |
| 61 fill_flags.setAntiAlias(true); | |
| 62 canvas->DrawRoundRect(fill_bounds, kCornerRadius, fill_flags); | |
| 63 | |
| 64 // Start with an outer dark stroke. | |
| 65 cc::PaintFlags stroke_flags; | |
| 66 stroke_flags.setStyle(cc::PaintFlags::kStroke_Style); | |
| 67 stroke_flags.setColor(SkColorSetA(SK_ColorBLACK, 0x2B)); | |
| 68 stroke_flags.setStrokeWidth(1); | |
| 69 stroke_flags.setAntiAlias(true); | |
| 70 gfx::RectF stroke_bounds(view.GetLocalBounds()); | |
| 71 stroke_bounds.Inset(gfx::InsetsF(0.5f)); | |
| 72 canvas->DrawRoundRect(stroke_bounds, kCornerRadius, stroke_flags); | |
| 73 | |
| 74 // There's a second, light stroke that matches the fill bounds. | |
|
Peter Kasting
2017/04/27 02:13:18
I'm a little worried about the radii of the corner
| |
| 75 stroke_bounds.Inset(kFillInsets); | |
| 76 stroke_flags.setColor(SkColorSetA(SK_ColorWHITE, 0x3F)); | |
| 77 canvas->DrawRoundRect(stroke_bounds, kCornerRadius, stroke_flags); | |
| 78 } | |
| 79 | |
| 80 gfx::Insets GetInsets() const override { | |
| 81 const int kLeftRightInset = 8; | |
| 82 const int kTopInset = 2; | |
| 83 const int kBottomInset = 4; | |
| 84 return gfx::Insets(kTopInset, kLeftRightInset, kBottomInset, | |
| 85 kLeftRightInset); | |
| 86 } | |
| 87 | |
| 88 gfx::Size GetMinimumSize() const override { | |
| 89 return gfx::Size(GetInsets().width(), GetInsets().height()); | |
| 90 } | |
| 91 | |
| 92 private: | |
| 93 DISALLOW_COPY_AND_ASSIGN(AvatarButtonThemedBorder); | |
| 94 }; | |
| 95 | |
| 96 #if !defined(OS_LINUX) | |
| 35 std::unique_ptr<views::Border> CreateBorder(const int normal_image_set[], | 97 std::unique_ptr<views::Border> CreateBorder(const int normal_image_set[], |
| 36 const int hot_image_set[], | 98 const int hot_image_set[], |
| 37 const int pushed_image_set[]) { | 99 const int pushed_image_set[]) { |
| 38 std::unique_ptr<views::LabelButtonAssetBorder> border( | 100 std::unique_ptr<views::LabelButtonAssetBorder> border( |
| 39 new views::LabelButtonAssetBorder(views::Button::STYLE_TEXTBUTTON)); | 101 new views::LabelButtonAssetBorder(views::Button::STYLE_TEXTBUTTON)); |
| 40 border->SetPainter(false, views::Button::STATE_NORMAL, | 102 border->SetPainter(false, views::Button::STATE_NORMAL, |
| 41 views::Painter::CreateImageGridPainter(normal_image_set)); | 103 views::Painter::CreateImageGridPainter(normal_image_set)); |
| 42 border->SetPainter(false, views::Button::STATE_HOVERED, | 104 border->SetPainter(false, views::Button::STATE_HOVERED, |
| 43 views::Painter::CreateImageGridPainter(hot_image_set)); | 105 views::Painter::CreateImageGridPainter(hot_image_set)); |
| 44 border->SetPainter(false, views::Button::STATE_PRESSED, | 106 border->SetPainter(false, views::Button::STATE_PRESSED, |
| 45 views::Painter::CreateImageGridPainter(pushed_image_set)); | 107 views::Painter::CreateImageGridPainter(pushed_image_set)); |
| 46 | 108 |
| 47 const int kLeftRightInset = 8; | 109 const int kLeftRightInset = 8; |
| 48 const int kTopInset = 2; | 110 const int kTopInset = 2; |
| 49 const int kBottomInset = 4; | 111 const int kBottomInset = 4; |
| 50 border->set_insets(gfx::Insets(kTopInset, kLeftRightInset, | 112 border->set_insets(gfx::Insets(kTopInset, kLeftRightInset, |
| 51 kBottomInset, kLeftRightInset)); | 113 kBottomInset, kLeftRightInset)); |
| 52 | 114 |
| 53 return std::move(border); | 115 return std::move(border); |
| 54 } | 116 } |
| 117 #endif | |
| 55 | 118 |
| 56 } // namespace | 119 } // namespace |
| 57 | 120 |
| 58 NewAvatarButton::NewAvatarButton(AvatarButtonDelegate* delegate, | 121 NewAvatarButton::NewAvatarButton(AvatarButtonDelegate* delegate, |
| 59 AvatarButtonStyle button_style, | 122 AvatarButtonStyle button_style, |
| 60 Profile* profile) | 123 Profile* profile) |
| 61 : LabelButton(delegate, base::string16()), | 124 : LabelButton(delegate, base::string16()), |
| 62 delegate_(delegate), | 125 delegate_(delegate), |
| 63 error_controller_(this, profile), | 126 error_controller_(this, profile), |
| 64 profile_(profile), | 127 profile_(profile), |
| 65 suppress_mouse_released_action_(false) { | 128 suppress_mouse_released_action_(false) { |
| 66 set_triggerable_event_flags( | 129 set_triggerable_event_flags( |
| 67 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON); | 130 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON); |
| 68 set_animate_on_state_change(false); | 131 set_animate_on_state_change(false); |
| 69 SetEnabledTextColors(SK_ColorWHITE); | 132 SetEnabledTextColors(SK_ColorWHITE); |
| 70 SetTextSubpixelRenderingEnabled(false); | 133 SetTextSubpixelRenderingEnabled(false); |
| 71 SetHorizontalAlignment(gfx::ALIGN_CENTER); | 134 SetHorizontalAlignment(gfx::ALIGN_CENTER); |
| 72 | 135 |
| 73 // The largest text height that fits in the button. If the font list height | 136 // The largest text height that fits in the button. If the font list height |
| 74 // is larger than this, it will be shrunk to match it. | 137 // is larger than this, it will be shrunk to match it. |
| 75 // TODO(noms): Calculate this constant algorithmically from the button's size. | 138 // TODO(noms): Calculate this constant algorithmically from the button's size. |
| 76 const int kDisplayFontHeight = 16; | 139 const int kDisplayFontHeight = 16; |
| 77 SetFontList( | 140 SetFontList( |
| 78 label()->font_list().DeriveWithHeightUpperBound(kDisplayFontHeight)); | 141 label()->font_list().DeriveWithHeightUpperBound(kDisplayFontHeight)); |
| 79 | 142 |
| 80 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | 143 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
| 144 generic_avatar_ = | |
| 145 rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_AVATAR).AsImageSkia(); | |
| 146 #if defined(OS_LINUX) | |
| 147 DCHECK_EQ(AvatarButtonStyle::THEMED, button_style); | |
| 148 SetBorder(base::MakeUnique<AvatarButtonThemedBorder>()); | |
| 149 SetInkDropMode(InkDropMode::ON); | |
| 150 #else // !defined(OS_LINUX) | |
| 81 if (button_style == AvatarButtonStyle::THEMED) { | 151 if (button_style == AvatarButtonStyle::THEMED) { |
| 152 SetBorder(base::MakeUnique<AvatarButtonThemedBorder>()); | |
| 153 SetInkDropMode(InkDropMode::ON); | |
| 82 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL); | 154 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL); |
| 83 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER); | 155 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER); |
| 84 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED); | 156 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED); |
| 85 | 157 |
| 86 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); | 158 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); |
| 87 generic_avatar_ = | |
| 88 *rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_AVATAR).ToImageSkia(); | |
| 89 #if defined(OS_WIN) | 159 #if defined(OS_WIN) |
| 90 } else if (base::win::GetVersion() < base::win::VERSION_WIN8) { | 160 } else if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
| 91 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL); | 161 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL); |
| 92 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER); | 162 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER); |
| 93 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED); | 163 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED); |
| 94 | 164 |
| 95 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); | 165 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); |
| 96 generic_avatar_ = | 166 generic_avatar_ = |
| 97 *rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_AVATAR).ToImageSkia(); | 167 *rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_AVATAR).ToImageSkia(); |
| 98 #endif | 168 #endif |
| 99 } else { | 169 } else { |
| 100 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_NORMAL); | 170 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_NORMAL); |
| 101 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_HOVER); | 171 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_HOVER); |
| 102 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); | 172 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); |
| 103 | 173 |
| 104 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); | 174 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); |
| 105 generic_avatar_ = | 175 generic_avatar_ = |
| 106 *rb->GetImageNamed(IDR_AVATAR_NATIVE_BUTTON_AVATAR).ToImageSkia(); | 176 *rb->GetImageNamed(IDR_AVATAR_NATIVE_BUTTON_AVATAR).ToImageSkia(); |
| 107 } | 177 } |
| 178 #endif // !defined(OS_LINUX) | |
| 108 | 179 |
| 109 g_browser_process->profile_manager()-> | 180 g_browser_process->profile_manager()-> |
| 110 GetProfileAttributesStorage().AddObserver(this); | 181 GetProfileAttributesStorage().AddObserver(this); |
| 111 Update(); | 182 Update(); |
| 112 SchedulePaint(); | 183 SchedulePaint(); |
| 113 } | 184 } |
| 114 | 185 |
| 115 NewAvatarButton::~NewAvatarButton() { | 186 NewAvatarButton::~NewAvatarButton() { |
| 116 g_browser_process->profile_manager()-> | 187 g_browser_process->profile_manager()-> |
| 117 GetProfileAttributesStorage().RemoveObserver(this); | 188 GetProfileAttributesStorage().RemoveObserver(this); |
| 118 } | 189 } |
| 119 | 190 |
| 120 bool NewAvatarButton::OnMousePressed(const ui::MouseEvent& event) { | 191 bool NewAvatarButton::OnMousePressed(const ui::MouseEvent& event) { |
| 121 // Prevent the bubble from being re-shown if it's already showing. | 192 // Prevent the bubble from being re-shown if it's already showing. |
| 122 suppress_mouse_released_action_ = ProfileChooserView::IsShowing(); | 193 suppress_mouse_released_action_ = ProfileChooserView::IsShowing(); |
| 123 return LabelButton::OnMousePressed(event); | 194 return LabelButton::OnMousePressed(event); |
| 124 } | 195 } |
| 125 | 196 |
| 126 void NewAvatarButton::OnMouseReleased(const ui::MouseEvent& event) { | 197 void NewAvatarButton::OnMouseReleased(const ui::MouseEvent& event) { |
| 127 if (suppress_mouse_released_action_) | 198 if (suppress_mouse_released_action_) |
| 128 suppress_mouse_released_action_ = false; | 199 suppress_mouse_released_action_ = false; |
| 129 else | 200 else |
| 130 LabelButton::OnMouseReleased(event); | 201 LabelButton::OnMouseReleased(event); |
| 131 } | 202 } |
| 132 | 203 |
| 204 SkColor NewAvatarButton::GetInkDropBaseColor() const { | |
| 205 return SK_ColorWHITE; | |
|
Evan Stade
2017/04/26 19:24:49
I stuck with white because the theme-colored backg
Peter Kasting
2017/04/27 02:13:18
Is the drop visible at all on a pure-white toolbar
| |
| 206 } | |
| 207 | |
| 208 std::unique_ptr<views::InkDropMask> NewAvatarButton::CreateInkDropMask() const { | |
| 209 return base::MakeUnique<views::RoundRectInkDropMask>(size(), kFillInsets, | |
| 210 kCornerRadius); | |
| 211 } | |
| 212 | |
| 213 void NewAvatarButton::NotifyClick(const ui::Event& event) { | |
| 214 LabelButton::NotifyClick(event); | |
| 215 | |
| 216 if (ProfileChooserView::IsShowing() && ink_drop_mode() == InkDropMode::ON) { | |
| 217 ProfileChooserView::GetCurrentBubbleWidget()->AddObserver(this); | |
| 218 AnimateInkDrop(views::InkDropState::ACTIVATED, | |
| 219 ui::LocatedEvent::FromIfValid(&event)); | |
| 220 } | |
| 221 } | |
| 222 | |
| 133 void NewAvatarButton::OnGestureEvent(ui::GestureEvent* event) { | 223 void NewAvatarButton::OnGestureEvent(ui::GestureEvent* event) { |
| 134 // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since | 224 // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since |
| 135 // no other UI button based on CustomButton appears to handle mouse | 225 // no other UI button based on CustomButton appears to handle mouse |
| 136 // right-click. If other cases are identified, it may make sense to move this | 226 // right-click. If other cases are identified, it may make sense to move this |
| 137 // check to CustomButton. | 227 // check to CustomButton. |
| 138 if (event->type() == ui::ET_GESTURE_LONG_PRESS) | 228 if (event->type() == ui::ET_GESTURE_LONG_PRESS) |
| 139 NotifyClick(*event); | 229 NotifyClick(*event); |
| 140 else | 230 else |
| 141 LabelButton::OnGestureEvent(event); | 231 LabelButton::OnGestureEvent(event); |
| 142 } | 232 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 164 if (profile_->GetPath() == profile_path) | 254 if (profile_->GetPath() == profile_path) |
| 165 Update(); | 255 Update(); |
| 166 } | 256 } |
| 167 | 257 |
| 168 void NewAvatarButton::OnProfileSupervisedUserIdChanged( | 258 void NewAvatarButton::OnProfileSupervisedUserIdChanged( |
| 169 const base::FilePath& profile_path) { | 259 const base::FilePath& profile_path) { |
| 170 if (profile_->GetPath() == profile_path) | 260 if (profile_->GetPath() == profile_path) |
| 171 Update(); | 261 Update(); |
| 172 } | 262 } |
| 173 | 263 |
| 264 void NewAvatarButton::OnWidgetClosing(views::Widget* widget) { | |
| 265 if (ink_drop_mode() == InkDropMode::ON) | |
| 266 AnimateInkDrop(views::InkDropState::DEACTIVATED, nullptr); | |
| 267 } | |
| 268 | |
| 174 void NewAvatarButton::Update() { | 269 void NewAvatarButton::Update() { |
| 175 ProfileAttributesStorage& storage = | 270 ProfileAttributesStorage& storage = |
| 176 g_browser_process->profile_manager()->GetProfileAttributesStorage(); | 271 g_browser_process->profile_manager()->GetProfileAttributesStorage(); |
| 177 | 272 |
| 178 // If we have a single local profile, then use the generic avatar | 273 // If we have a single local profile, then use the generic avatar |
| 179 // button instead of the profile name. Never use the generic button if | 274 // button instead of the profile name. Never use the generic button if |
| 180 // the active profile is Guest. | 275 // the active profile is Guest. |
| 181 const bool use_generic_button = | 276 const bool use_generic_button = |
| 182 !profile_->IsGuestSession() && | 277 !profile_->IsGuestSession() && |
| 183 storage.GetNumberOfProfiles() == 1 && | 278 storage.GetNumberOfProfiles() == 1 && |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 208 } | 303 } |
| 209 | 304 |
| 210 // If we are not using the generic button, then reset the spacing between | 305 // If we are not using the generic button, then reset the spacing between |
| 211 // the text and the possible authentication error icon. | 306 // the text and the possible authentication error icon. |
| 212 const int kDefaultImageTextSpacing = 5; | 307 const int kDefaultImageTextSpacing = 5; |
| 213 SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing); | 308 SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing); |
| 214 | 309 |
| 215 PreferredSizeChanged(); | 310 PreferredSizeChanged(); |
| 216 delegate_->ButtonPreferredSizeChanged(); | 311 delegate_->ButtonPreferredSizeChanged(); |
| 217 } | 312 } |
| OLD | NEW |