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.
5 #include "chrome/browser/ui/views/passwords/credentials_item_view.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
9 #include "chrome/grit/generated_resources.h"
10 #include "components/autofill/core/common/password_form.h"
11 #include "grit/theme_resources.h"
12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/gfx/canvas.h"
15 #include "ui/gfx/image/image.h"
16 #include "ui/gfx/path.h"
17 #include "ui/views/border.h"
18 #include "ui/views/controls/image_view.h"
19 #include "ui/views/controls/label.h"
22 // The default spacing between the icon and text.
23 const int kSpacing
= 5;
25 gfx::Size
GetTextLabelsSize(const views::Label
* upper_label
,
26 const views::Label
* lower_label
) {
27 gfx::Size upper_label_size
= upper_label
->GetPreferredSize();
28 gfx::Size lower_label_size
= lower_label
? lower_label
->GetPreferredSize() :
30 return gfx::Size(std::max(upper_label_size
.width(), lower_label_size
.width()),
31 upper_label_size
.height() + lower_label_size
.height());
34 // Returns the bold upper text for the button.
35 base::string16
GetUpperLabelText(const autofill::PasswordForm
& form
,
36 CredentialsItemView::Style style
) {
37 const base::string16
& name
= form
.display_name
.empty() ? form
.username_value
40 case CredentialsItemView::ACCOUNT_CHOOSER
:
42 case CredentialsItemView::AUTO_SIGNIN
:
43 return l10n_util::GetStringFUTF16(IDS_MANAGE_PASSWORDS_AUTO_SIGNIN_TITLE
,
47 return base::string16();
50 // Returns the lower text for the button.
51 base::string16
GetLowerLabelText(const autofill::PasswordForm
& form
,
52 CredentialsItemView::Style style
) {
53 if (!form
.federation_url
.is_empty()) {
54 return l10n_util::GetStringFUTF16(
55 IDS_MANAGE_PASSWORDS_IDENTITY_PROVIDER
,
56 base::UTF8ToUTF16(form
.federation_url
.host()));
58 return form
.display_name
.empty() ? base::string16() : form
.username_value
;
61 class CircularImageView
: public views::ImageView
{
63 CircularImageView() = default;
67 void OnPaint(gfx::Canvas
* canvas
) override
;
69 DISALLOW_COPY_AND_ASSIGN(CircularImageView
);
72 void CircularImageView::OnPaint(gfx::Canvas
* canvas
) {
73 // Display the avatar picture as a circle.
74 gfx::Rect
bounds(GetImageBounds());
75 gfx::Path circular_mask
;
76 circular_mask
.addCircle(
77 SkIntToScalar(bounds
.x() + bounds
.right()) / 2,
78 SkIntToScalar(bounds
.y() + bounds
.bottom()) / 2,
79 SkIntToScalar(std::min(bounds
.height(), bounds
.width())) / 2);
80 canvas
->ClipPath(circular_mask
, true);
81 ImageView::OnPaint(canvas
);
86 CredentialsItemView::CredentialsItemView(
87 views::ButtonListener
* button_listener
,
88 const autofill::PasswordForm
* form
,
89 password_manager::CredentialType credential_type
,
91 net::URLRequestContextGetter
* request_context
)
92 : LabelButton(button_listener
, base::string16()),
94 credential_type_(credential_type
),
95 upper_label_(nullptr),
96 lower_label_(nullptr),
97 weak_ptr_factory_(this) {
98 set_notify_enter_exit_on_child(true);
99 // Create an image-view for the avatar. Make sure it ignores events so that
100 // the parent can receive the events instead.
101 image_view_
= new CircularImageView
;
102 image_view_
->set_interactive(false);
103 gfx::Image image
= ResourceBundle::GetSharedInstance().GetImageNamed(
104 IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE
);
105 DCHECK(image
.Width() >= kAvatarImageSize
&&
106 image
.Height() >= kAvatarImageSize
);
107 UpdateAvatar(image
.AsImageSkia());
108 if (form_
->icon_url
.is_valid()) {
109 // Fetch the actual avatar.
110 AccountAvatarFetcher
* fetcher
= new AccountAvatarFetcher(
111 form_
->icon_url
, weak_ptr_factory_
.GetWeakPtr());
112 fetcher
->Start(request_context
);
114 AddChildView(image_view_
);
116 ui::ResourceBundle
* rb
= &ui::ResourceBundle::GetSharedInstance();
117 upper_label_
= new views::Label(
118 GetUpperLabelText(*form_
, style
),
119 rb
->GetFontList(ui::ResourceBundle::BoldFont
));
120 upper_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
121 AddChildView(upper_label_
);
123 base::string16 lower_text
= GetLowerLabelText(*form_
, style
);
124 if (!lower_text
.empty()) {
125 lower_label_
= new views::Label(
126 lower_text
, rb
->GetFontList(ui::ResourceBundle::SmallFont
));
127 lower_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
128 lower_label_
->SetEnabled(false);
129 AddChildView(lower_label_
);
135 CredentialsItemView::~CredentialsItemView() = default;
137 gfx::Size
CredentialsItemView::GetPreferredSize() const {
138 gfx::Size labels_size
= GetTextLabelsSize(upper_label_
, lower_label_
);
139 gfx::Size size
= gfx::Size(kAvatarImageSize
+ labels_size
.width(),
140 std::max(kAvatarImageSize
, labels_size
.height()));
141 const gfx::Insets
insets(GetInsets());
142 size
.Enlarge(insets
.width(), insets
.height());
143 size
.Enlarge(kSpacing
, 0);
145 // Make the size at least as large as the minimum size needed by the border.
146 size
.SetToMax(border() ? border()->GetMinimumSize() : gfx::Size());
150 int CredentialsItemView::GetHeightForWidth(int w
) const {
151 return View::GetHeightForWidth(w
);
154 void CredentialsItemView::Layout() {
155 gfx::Rect
child_area(GetChildAreaBounds());
156 child_area
.Inset(GetInsets());
158 gfx::Size
image_size(image_view_
->GetPreferredSize());
159 image_size
.SetToMin(child_area
.size());
160 gfx::Point
image_origin(child_area
.origin());
161 image_origin
.Offset(0, (child_area
.height() - image_size
.height()) / 2);
162 image_view_
->SetBoundsRect(gfx::Rect(image_origin
, image_size
));
164 gfx::Size full_name_size
= upper_label_
->GetPreferredSize();
165 gfx::Size username_size
=
166 lower_label_
? lower_label_
->GetPreferredSize() : gfx::Size();
167 int y_offset
= (child_area
.height() -
168 (full_name_size
.height() + username_size
.height())) / 2;
169 gfx::Point
label_origin(image_origin
.x() + image_size
.width() + kSpacing
,
170 child_area
.origin().y() + y_offset
);
171 upper_label_
->SetBoundsRect(gfx::Rect(label_origin
, full_name_size
));
173 label_origin
.Offset(0, full_name_size
.height());
174 lower_label_
->SetBoundsRect(gfx::Rect(label_origin
, username_size
));
178 void CredentialsItemView::UpdateAvatar(const gfx::ImageSkia
& image
) {
179 image_view_
->SetImage(ScaleImageForAccountAvatar(image
));