| 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 "base/win/windows_version.h" | 9 #include "base/win/windows_version.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "ui/gfx/color_palette.h" | 21 #include "ui/gfx/color_palette.h" |
| 22 #include "ui/gfx/geometry/vector2d.h" | 22 #include "ui/gfx/geometry/vector2d.h" |
| 23 #include "ui/gfx/paint_vector_icon.h" | 23 #include "ui/gfx/paint_vector_icon.h" |
| 24 #include "ui/gfx/vector_icons_public.h" | 24 #include "ui/gfx/vector_icons_public.h" |
| 25 #include "ui/views/border.h" | 25 #include "ui/views/border.h" |
| 26 #include "ui/views/controls/button/label_button_border.h" | 26 #include "ui/views/controls/button/label_button_border.h" |
| 27 #include "ui/views/painter.h" | 27 #include "ui/views/painter.h" |
| 28 | 28 |
| 29 namespace { | 29 namespace { |
| 30 | 30 |
| 31 std::unique_ptr<views::Border> CreateBorder(const int normal_image_set[], | 31 std::unique_ptr<views::Border> CreateBorder(const int normal_image_set[], |
| 32 const int hot_image_set[], | 32 const int hot_image_set[], |
| 33 const int pushed_image_set[]) { | 33 const int pushed_image_set[]) { |
| 34 std::unique_ptr<views::LabelButtonAssetBorder> border( | 34 std::unique_ptr<views::LabelButtonAssetBorder> border( |
| 35 new views::LabelButtonAssetBorder(views::Button::STYLE_TEXTBUTTON)); | 35 new views::LabelButtonAssetBorder(views::Button::STYLE_TEXTBUTTON)); |
| 36 border->SetPainter(false, views::Button::STATE_NORMAL, | 36 border->SetPainter(false, views::Button::STATE_NORMAL, |
| 37 views::Painter::CreateImageGridPainter(normal_image_set)); | 37 views::Painter::CreateImageGridPainter(normal_image_set)); |
| 38 border->SetPainter(false, views::Button::STATE_HOVERED, | 38 border->SetPainter(false, views::Button::STATE_HOVERED, |
| 39 views::Painter::CreateImageGridPainter(hot_image_set)); | 39 views::Painter::CreateImageGridPainter(hot_image_set)); |
| 40 border->SetPainter(false, views::Button::STATE_PRESSED, | 40 border->SetPainter(false, views::Button::STATE_PRESSED, |
| 41 views::Painter::CreateImageGridPainter(pushed_image_set)); | 41 views::Painter::CreateImageGridPainter(pushed_image_set)); |
| 42 | 42 |
| 43 const int kLeftRightInset = 8; | 43 const int kLeftRightInset = 8; |
| 44 const int kTopInset = 2; | 44 const int kTopInset = 2; |
| 45 const int kBottomInset = 4; | 45 const int kBottomInset = 4; |
| 46 border->set_insets(gfx::Insets(kTopInset, kLeftRightInset, | 46 border->set_insets(gfx::Insets(kTopInset, kLeftRightInset, |
| 47 kBottomInset, kLeftRightInset)); | 47 kBottomInset, kLeftRightInset)); |
| 48 | 48 |
| 49 return std::move(border); | 49 return std::move(border); |
| 50 } | 50 } |
| 51 | 51 |
| 52 } // namespace | 52 } // namespace |
| 53 | 53 |
| 54 NewAvatarButton::NewAvatarButton(AvatarButtonDelegate* delegate, | 54 AvatarButton::AvatarButton(AvatarButtonDelegate* delegate, |
| 55 AvatarButtonStyle button_style, | 55 AvatarButtonStyle button_style, |
| 56 Profile* profile) | 56 Profile* profile) |
| 57 : LabelButton(delegate, base::string16()), | 57 : LabelButton(delegate, base::string16()), |
| 58 delegate_(delegate), | 58 delegate_(delegate), |
| 59 error_controller_(this, profile), | 59 error_controller_(this, profile), |
| 60 profile_(profile), | 60 profile_(profile), |
| 61 suppress_mouse_released_action_(false) { | 61 suppress_mouse_released_action_(false) { |
| 62 set_triggerable_event_flags( | 62 set_triggerable_event_flags( |
| 63 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON); | 63 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON); |
| 64 set_animate_on_state_change(false); | 64 set_animate_on_state_change(false); |
| 65 SetEnabledTextColors(SK_ColorWHITE); | 65 SetEnabledTextColors(SK_ColorWHITE); |
| 66 SetTextSubpixelRenderingEnabled(false); | 66 SetTextSubpixelRenderingEnabled(false); |
| 67 SetHorizontalAlignment(gfx::ALIGN_CENTER); | 67 SetHorizontalAlignment(gfx::ALIGN_CENTER); |
| 68 | 68 |
| 69 // The largest text height that fits in the button. If the font list height | |
| 70 // is larger than this, it will be shrunk to match it. | |
| 71 // TODO(noms): Calculate this constant algorithmically from the button's size. | |
| 72 const int kDisplayFontHeight = 16; | |
| 73 SetFontList( | |
| 74 label()->font_list().DeriveWithHeightUpperBound(kDisplayFontHeight)); | |
| 75 | |
| 76 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | |
| 77 if (button_style == AvatarButtonStyle::THEMED) { | |
| 78 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL); | |
| 79 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER); | |
| 80 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED); | |
| 81 | |
| 82 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); | |
| 83 generic_avatar_ = | |
| 84 *rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_AVATAR).ToImageSkia(); | |
| 85 #if defined(OS_WIN) | |
| 86 } else if (base::win::GetVersion() < base::win::VERSION_WIN8) { | |
| 87 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL); | |
| 88 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER); | |
| 89 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED); | |
| 90 | |
| 91 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); | |
| 92 generic_avatar_ = | |
| 93 *rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_AVATAR).ToImageSkia(); | |
| 94 #endif | |
| 95 } else { | |
| 96 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_NORMAL); | |
| 97 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_HOVER); | |
| 98 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); | |
| 99 | |
| 100 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); | |
| 101 generic_avatar_ = | |
| 102 *rb->GetImageNamed(IDR_AVATAR_NATIVE_BUTTON_AVATAR).ToImageSkia(); | |
| 103 } | |
| 104 | |
| 105 g_browser_process->profile_manager()-> | 69 g_browser_process->profile_manager()-> |
| 106 GetProfileAttributesStorage().AddObserver(this); | 70 GetProfileAttributesStorage().AddObserver(this); |
| 107 Update(); | 71 } |
| 108 SchedulePaint(); | 72 |
| 109 } | 73 AvatarButton::~AvatarButton() { |
| 110 | |
| 111 NewAvatarButton::~NewAvatarButton() { | |
| 112 g_browser_process->profile_manager()-> | 74 g_browser_process->profile_manager()-> |
| 113 GetProfileAttributesStorage().RemoveObserver(this); | 75 GetProfileAttributesStorage().RemoveObserver(this); |
| 114 } | 76 } |
| 115 | 77 |
| 116 bool NewAvatarButton::OnMousePressed(const ui::MouseEvent& event) { | 78 bool AvatarButton::OnMousePressed(const ui::MouseEvent& event) { |
| 117 // Prevent the bubble from being re-shown if it's already showing. | 79 // Prevent the bubble from being re-shown if it's already showing. |
| 118 suppress_mouse_released_action_ = ProfileChooserView::IsShowing(); | 80 suppress_mouse_released_action_ = ProfileChooserView::IsShowing(); |
| 119 return LabelButton::OnMousePressed(event); | 81 return LabelButton::OnMousePressed(event); |
| 120 } | 82 } |
| 121 | 83 |
| 122 void NewAvatarButton::OnMouseReleased(const ui::MouseEvent& event) { | 84 void AvatarButton::OnMouseReleased(const ui::MouseEvent& event) { |
| 123 if (suppress_mouse_released_action_) | 85 if (suppress_mouse_released_action_) |
| 124 suppress_mouse_released_action_ = false; | 86 suppress_mouse_released_action_ = false; |
| 125 else | 87 else |
| 126 LabelButton::OnMouseReleased(event); | 88 LabelButton::OnMouseReleased(event); |
| 127 } | 89 } |
| 128 | 90 |
| 129 void NewAvatarButton::OnGestureEvent(ui::GestureEvent* event) { | 91 void AvatarButton::OnGestureEvent(ui::GestureEvent* event) { |
| 130 // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since | 92 // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since |
| 131 // no other UI button based on CustomButton appears to handle mouse | 93 // no other UI button based on CustomButton appears to handle mouse |
| 132 // right-click. If other cases are identified, it may make sense to move this | 94 // right-click. If other cases are identified, it may make sense to move this |
| 133 // check to CustomButton. | 95 // check to CustomButton. |
| 134 if (event->type() == ui::ET_GESTURE_LONG_PRESS) | 96 if (event->type() == ui::ET_GESTURE_LONG_PRESS) |
| 135 NotifyClick(*event); | 97 NotifyClick(*event); |
| 136 else | 98 else |
| 137 LabelButton::OnGestureEvent(event); | 99 LabelButton::OnGestureEvent(event); |
| 138 } | 100 } |
| 139 | 101 |
| 140 void NewAvatarButton::OnAvatarErrorChanged() { | 102 void AvatarButton::OnAvatarErrorChanged() { |
| 141 Update(); | 103 Update(); |
| 142 } | 104 } |
| 143 | 105 |
| 144 void NewAvatarButton::OnProfileAdded(const base::FilePath& profile_path) { | 106 void AvatarButton::OnProfileAdded(const base::FilePath& profile_path) { |
| 145 Update(); | 107 Update(); |
| 146 } | 108 } |
| 147 | 109 |
| 148 void NewAvatarButton::OnProfileWasRemoved( | 110 void AvatarButton::OnProfileWasRemoved( |
| 149 const base::FilePath& profile_path, | 111 const base::FilePath& profile_path, |
| 150 const base::string16& profile_name) { | 112 const base::string16& profile_name) { |
| 151 // If deleting the active profile, don't bother updating the avatar | 113 // If deleting the active profile, don't bother updating the avatar |
| 152 // button, as the browser window is being closed anyway. | 114 // button, as the browser window is being closed anyway. |
| 153 if (profile_->GetPath() != profile_path) | 115 if (profile_->GetPath() != profile_path) |
| 154 Update(); | 116 Update(); |
| 155 } | 117 } |
| 156 | 118 |
| 157 void NewAvatarButton::OnProfileNameChanged( | 119 void AvatarButton::OnProfileNameChanged( |
| 158 const base::FilePath& profile_path, | 120 const base::FilePath& profile_path, |
| 159 const base::string16& old_profile_name) { | 121 const base::string16& old_profile_name) { |
| 160 if (profile_->GetPath() == profile_path) | 122 if (profile_->GetPath() == profile_path) |
| 161 Update(); | 123 Update(); |
| 162 } | 124 } |
| 163 | 125 |
| 164 void NewAvatarButton::OnProfileSupervisedUserIdChanged( | 126 void AvatarButton::OnProfileSupervisedUserIdChanged( |
| 165 const base::FilePath& profile_path) { | 127 const base::FilePath& profile_path) { |
| 166 if (profile_->GetPath() == profile_path) | 128 if (profile_->GetPath() == profile_path) |
| 167 Update(); | 129 Update(); |
| 168 } | 130 } |
| 169 | 131 |
| 170 void NewAvatarButton::Update() { | 132 void AvatarButton::Update() { |
| 171 ProfileAttributesStorage& storage = | 133 ProfileAttributesStorage& storage = |
| 172 g_browser_process->profile_manager()->GetProfileAttributesStorage(); | 134 g_browser_process->profile_manager()->GetProfileAttributesStorage(); |
| 173 | 135 |
| 174 // If we have a single local profile, then use the generic avatar | 136 // If we have a single local profile, then use the generic avatar |
| 175 // button instead of the profile name. Never use the generic button if | 137 // button instead of the profile name. Never use the generic button if |
| 176 // the active profile is Guest. | 138 // the active profile is Guest. |
| 177 const bool use_generic_button = | 139 const bool use_generic_button = |
| 178 !profile_->IsGuestSession() && | 140 !profile_->IsGuestSession() && |
| 179 storage.GetNumberOfProfiles() == 1 && | 141 storage.GetNumberOfProfiles() == 1 && |
| 180 !storage.GetAllProfilesAttributes().front()->IsAuthenticated(); | 142 !storage.GetAllProfilesAttributes().front()->IsAuthenticated(); |
| 181 | 143 |
| 144 UpdateButton(use_generic_button, profile_, &error_controller_); |
| 145 |
| 146 PreferredSizeChanged(); |
| 147 delegate_->ButtonPreferredSizeChanged(); |
| 148 } |
| 149 |
| 150 |
| 151 //----------------------------------------------------------------------- |
| 152 //----------------------------------------------------------------------- |
| 153 //----------------------------------------------------------------------- |
| 154 |
| 155 NewAvatarButton::NewAvatarButton(AvatarButtonDelegate* delegate, |
| 156 AvatarButtonStyle button_style, |
| 157 Profile* profile) : AvatarButton(delegate, button_style, profile) { |
| 158 SetEnabledTextColors(SK_ColorWHITE); |
| 159 SetTextSubpixelRenderingEnabled(false); |
| 160 SetHorizontalAlignment(gfx::ALIGN_CENTER); |
| 161 |
| 162 // The largest text height that fits in the button. If the font list height |
| 163 // is larger than this, it will be shrunk to match it. |
| 164 // TODO(noms): Calculate this constant algorithmically from the button's size. |
| 165 const int kDisplayFontHeight = 16; |
| 166 SetFontList( |
| 167 label()->font_list().DeriveWithHeightUpperBound(kDisplayFontHeight)); |
| 168 |
| 169 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); |
| 170 if (button_style == AvatarButtonStyle::THEMED) { |
| 171 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL); |
| 172 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER); |
| 173 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED); |
| 174 |
| 175 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); |
| 176 generic_avatar_ = |
| 177 *rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_AVATAR).ToImageSkia(); |
| 178 #if defined(OS_WIN) |
| 179 } |
| 180 else if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
| 181 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL); |
| 182 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER); |
| 183 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED); |
| 184 |
| 185 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); |
| 186 generic_avatar_ = |
| 187 *rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_AVATAR).ToImageSkia(); |
| 188 #endif |
| 189 } |
| 190 else { |
| 191 const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_NORMAL); |
| 192 const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_HOVER); |
| 193 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); |
| 194 |
| 195 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); |
| 196 generic_avatar_ = |
| 197 *rb->GetImageNamed(IDR_AVATAR_NATIVE_BUTTON_AVATAR).ToImageSkia(); |
| 198 } |
| 199 Update(); |
| 200 SchedulePaint(); |
| 201 } |
| 202 |
| 203 NewAvatarButton::~NewAvatarButton() {} |
| 204 |
| 205 void NewAvatarButton::UpdateButton(bool use_generic_button, Profile* profile, Av
atarButtonErrorController* error_controller) { |
| 182 SetText(use_generic_button | 206 SetText(use_generic_button |
| 183 ? base::string16() | 207 ? base::string16() |
| 184 : profiles::GetAvatarButtonTextForProfile(profile_)); | 208 : profiles::GetAvatarButtonTextForProfile(profile)); |
| 185 | 209 |
| 186 // If the button has no text, clear the text shadows to make sure the | 210 // If the button has no text, clear the text shadows to make sure the |
| 187 // image is centered correctly. | 211 // image is centered correctly. |
| 188 SetTextShadows( | 212 SetTextShadows( |
| 189 use_generic_button | 213 use_generic_button |
| 190 ? gfx::ShadowValues() | 214 ? gfx::ShadowValues() |
| 191 : gfx::ShadowValues( | 215 : gfx::ShadowValues( |
| 192 10, gfx::ShadowValue(gfx::Vector2d(), 1.0f, SK_ColorDKGRAY))); | 216 10, gfx::ShadowValue(gfx::Vector2d(), 1.0f, SK_ColorDKGRAY))); |
| 193 | 217 |
| 194 // We want the button to resize if the new text is shorter. | 218 // We want the button to resize if the new text is shorter. |
| 195 SetMinSize(gfx::Size()); | 219 SetMinSize(gfx::Size()); |
| 196 | 220 |
| 197 if (use_generic_button) { | 221 if (use_generic_button) { |
| 198 SetImage(views::Button::STATE_NORMAL, generic_avatar_); | 222 SetImage(views::Button::STATE_NORMAL, generic_avatar_); |
| 199 } else if (error_controller_.HasAvatarError()) { | 223 } |
| 224 else if (error_controller->HasAvatarError()) { |
| 200 if (switches::IsMaterialDesignUserMenu()) { | 225 if (switches::IsMaterialDesignUserMenu()) { |
| 201 SetImage(views::Button::STATE_NORMAL, | 226 SetImage(views::Button::STATE_NORMAL, |
| 202 gfx::CreateVectorIcon(gfx::VectorIconId::SYNC_PROBLEM, 16, | 227 gfx::CreateVectorIcon(gfx::VectorIconId::SYNC_PROBLEM, 16, |
| 203 gfx::kGoogleRed700)); | 228 gfx::kGoogleRed700)); |
| 204 } else { | 229 } |
| 230 else { |
| 205 SetImage(views::Button::STATE_NORMAL, | 231 SetImage(views::Button::STATE_NORMAL, |
| 206 gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 13, | 232 gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 13, |
| 207 gfx::kGoogleYellow700)); | 233 gfx::kGoogleYellow700)); |
| 208 } | 234 } |
| 209 } else { | 235 } |
| 236 else { |
| 210 SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia()); | 237 SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia()); |
| 211 } | 238 } |
| 212 | 239 |
| 213 // If we are not using the generic button, then reset the spacing between | 240 // If we are not using the generic button, then reset the spacing between |
| 214 // the text and the possible authentication error icon. | 241 // the text and the possible authentication error icon. |
| 215 const int kDefaultImageTextSpacing = 5; | 242 const int kDefaultImageTextSpacing = 5; |
| 216 SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing); | 243 SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing); |
| 217 | 244 } |
| 218 PreferredSizeChanged(); | 245 |
| 219 delegate_->ButtonPreferredSizeChanged(); | 246 |
| 220 } | |
| OLD | NEW |