• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/views/profiles/new_avatar_button.h"
6 
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/win/windows_version.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/profiles/profile_manager.h"
11 #include "chrome/browser/profiles/profiles_state.h"
12 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "components/signin/core/browser/profile_oauth2_token_service.h"
15 #include "grit/generated_resources.h"
16 #include "grit/theme_resources.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/color_utils.h"
21 #include "ui/gfx/font_list.h"
22 #include "ui/gfx/text_constants.h"
23 #include "ui/gfx/text_elider.h"
24 #include "ui/views/border.h"
25 #include "ui/views/controls/button/label_button_border.h"
26 #include "ui/views/painter.h"
27 
28 namespace {
29 
CreateBorder(const int normal_image_set[],const int hot_image_set[],const int pushed_image_set[])30 scoped_ptr<views::Border> CreateBorder(const int normal_image_set[],
31                                        const int hot_image_set[],
32                                        const int pushed_image_set[]) {
33   scoped_ptr<views::LabelButtonBorder> border(
34       new views::LabelButtonBorder(views::Button::STYLE_TEXTBUTTON));
35   border->SetPainter(false, views::Button::STATE_NORMAL,
36       views::Painter::CreateImageGridPainter(normal_image_set));
37   border->SetPainter(false, views::Button::STATE_HOVERED,
38       views::Painter::CreateImageGridPainter(hot_image_set));
39   border->SetPainter(false, views::Button::STATE_PRESSED,
40       views::Painter::CreateImageGridPainter(pushed_image_set));
41 
42   const int kLeftRightInset = 10;
43   const int kTopInset = 0;
44   const int kBottomInset = 4;
45   border->set_insets(gfx::Insets(kTopInset, kLeftRightInset,
46                                  kBottomInset, kLeftRightInset));
47 
48   return border.PassAs<views::Border>();
49 }
50 
GetElidedText(const base::string16 & original_text)51 base::string16 GetElidedText(const base::string16& original_text) {
52   // Maximum characters the button can be before the text will get elided.
53   const int kMaxCharactersToDisplay = 15;
54   const gfx::FontList font_list;
55   return gfx::ElideText(original_text, font_list,
56                         font_list.GetExpectedTextWidth(kMaxCharactersToDisplay),
57                         gfx::ELIDE_TAIL);
58 }
59 
GetButtonText(Profile * profile)60 base::string16 GetButtonText(Profile* profile) {
61   base::string16 name = GetElidedText(
62       profiles::GetAvatarNameForProfile(profile));
63   if (profile->IsSupervised())
64     name = l10n_util::GetStringFUTF16(IDS_MANAGED_USER_NEW_AVATAR_LABEL, name);
65   return name;
66 }
67 
68 }  // namespace
69 
NewAvatarButton(views::ButtonListener * listener,const base::string16 & profile_name,AvatarButtonStyle button_style,Browser * browser)70 NewAvatarButton::NewAvatarButton(
71     views::ButtonListener* listener,
72     const base::string16& profile_name,
73     AvatarButtonStyle button_style,
74     Browser* browser)
75     : MenuButton(listener, GetButtonText(browser->profile()), NULL, true),
76       browser_(browser) {
77   set_animate_on_state_change(false);
78   SetTextColor(views::Button::STATE_NORMAL, SK_ColorWHITE);
79   SetTextColor(views::Button::STATE_HOVERED, SK_ColorWHITE);
80   SetTextColor(views::Button::STATE_PRESSED, SK_ColorWHITE);
81   SetTextShadows(gfx::ShadowValues(10,
82       gfx::ShadowValue(gfx::Point(), 1.0f, SK_ColorDKGRAY)));
83   SetTextSubpixelRenderingEnabled(false);
84 
85   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
86   if (button_style == THEMED_BUTTON) {
87     const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL);
88     const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER);
89     const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED);
90 
91     SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
92     set_menu_marker(
93         rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_DROPARROW).ToImageSkia());
94 #if defined(OS_WIN)
95   } else if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
96     const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_METRO_BUTTON_NORMAL);
97     const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_METRO_BUTTON_HOVER);
98     const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_METRO_BUTTON_PRESSED);
99 
100     SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
101     set_menu_marker(
102         rb->GetImageNamed(IDR_AVATAR_METRO_BUTTON_DROPARROW).ToImageSkia());
103 #endif
104   } else {
105     const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL);
106     const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER);
107     const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED);
108 
109     SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
110     set_menu_marker(
111         rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_DROPARROW).ToImageSkia());
112   }
113 
114   g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver(this);
115 
116   // Subscribe to authentication error changes so that the avatar button can
117   // update itself.  Note that guest mode profiles won't have a token service.
118   SigninErrorController* error =
119       profiles::GetSigninErrorController(browser_->profile());
120   if (error) {
121     error->AddObserver(this);
122     OnErrorChanged();
123   }
124 
125   SchedulePaint();
126 }
127 
~NewAvatarButton()128 NewAvatarButton::~NewAvatarButton() {
129   g_browser_process->profile_manager()->
130       GetProfileInfoCache().RemoveObserver(this);
131   SigninErrorController* error =
132       profiles::GetSigninErrorController(browser_->profile());
133   if (error)
134     error->RemoveObserver(this);
135 }
136 
OnProfileAdded(const base::FilePath & profile_path)137 void NewAvatarButton::OnProfileAdded(const base::FilePath& profile_path) {
138   UpdateAvatarButtonAndRelayoutParent();
139 }
140 
OnProfileWasRemoved(const base::FilePath & profile_path,const base::string16 & profile_name)141 void NewAvatarButton::OnProfileWasRemoved(
142       const base::FilePath& profile_path,
143       const base::string16& profile_name) {
144   UpdateAvatarButtonAndRelayoutParent();
145 }
146 
OnProfileNameChanged(const base::FilePath & profile_path,const base::string16 & old_profile_name)147 void NewAvatarButton::OnProfileNameChanged(
148       const base::FilePath& profile_path,
149       const base::string16& old_profile_name) {
150   UpdateAvatarButtonAndRelayoutParent();
151 }
152 
OnProfileSupervisedUserIdChanged(const base::FilePath & profile_path)153 void NewAvatarButton::OnProfileSupervisedUserIdChanged(
154       const base::FilePath& profile_path) {
155   UpdateAvatarButtonAndRelayoutParent();
156 }
157 
OnErrorChanged()158 void NewAvatarButton::OnErrorChanged() {
159   gfx::ImageSkia icon;
160 
161   // If there is an error, show an warning icon.
162   const SigninErrorController* error =
163       profiles::GetSigninErrorController(browser_->profile());
164   if (error && error->HasError()) {
165     icon = *ui::ResourceBundle::GetSharedInstance().GetImageNamed(
166         IDR_ICON_PROFILES_AVATAR_BUTTON_ERROR).ToImageSkia();
167   }
168 
169   SetImage(views::Button::STATE_NORMAL, icon);
170   UpdateAvatarButtonAndRelayoutParent();
171 }
172 
UpdateAvatarButtonAndRelayoutParent()173 void NewAvatarButton::UpdateAvatarButtonAndRelayoutParent() {
174   // We want the button to resize if the new text is shorter.
175   SetText(GetButtonText(browser_->profile()));
176   set_min_size(gfx::Size());
177   InvalidateLayout();
178 
179   // Because the width of the button might have changed, the parent browser
180   // frame needs to recalculate the button bounds and redraw it.
181   if (parent())
182     parent()->Layout();
183 }
184