blob: 90f5b1eb120b0d8a2f7a301bfeae3075bde94fe0 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/passwords/credentials_item_view.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
#include "chrome/grit/generated_resources.h"
#include "components/autofill/core/common/password_form.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/path.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
namespace {
// The default spacing between the icon and text.
const int kSpacing = 10;
gfx::Size GetTextLabelsSize(const views::Label* upper_label,
const views::Label* lower_label) {
gfx::Size upper_label_size = upper_label ? upper_label->GetPreferredSize()
: gfx::Size();
gfx::Size lower_label_size = lower_label ? lower_label->GetPreferredSize()
: gfx::Size();
return gfx::Size(std::max(upper_label_size.width(), lower_label_size.width()),
upper_label_size.height() + lower_label_size.height());
}
class CircularImageView : public views::ImageView {
public:
CircularImageView() = default;
private:
// views::ImageView:
void OnPaint(gfx::Canvas* canvas) override;
DISALLOW_COPY_AND_ASSIGN(CircularImageView);
};
void CircularImageView::OnPaint(gfx::Canvas* canvas) {
// Display the avatar picture as a circle.
gfx::Rect bounds(GetImageBounds());
gfx::Path circular_mask;
circular_mask.addCircle(
SkIntToScalar(bounds.x() + bounds.right()) / 2,
SkIntToScalar(bounds.y() + bounds.bottom()) / 2,
SkIntToScalar(std::min(bounds.height(), bounds.width())) / 2);
canvas->ClipPath(circular_mask, true);
ImageView::OnPaint(canvas);
}
} // namespace
CredentialsItemView::CredentialsItemView(
views::ButtonListener* button_listener,
const autofill::PasswordForm* form,
password_manager::CredentialType credential_type,
const base::string16& upper_text,
const base::string16& lower_text,
net::URLRequestContextGetter* request_context)
: LabelButton(button_listener, base::string16()),
form_(form),
credential_type_(credential_type),
upper_label_(nullptr),
lower_label_(nullptr),
weak_ptr_factory_(this) {
set_notify_enter_exit_on_child(true);
// Create an image-view for the avatar. Make sure it ignores events so that
// the parent can receive the events instead.
image_view_ = new CircularImageView;
image_view_->set_interactive(false);
gfx::Image image = ResourceBundle::GetSharedInstance().GetImageNamed(
IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE);
DCHECK(image.Width() >= kAvatarImageSize &&
image.Height() >= kAvatarImageSize);
UpdateAvatar(image.AsImageSkia());
if (form_->icon_url.is_valid()) {
// Fetch the actual avatar.
AccountAvatarFetcher* fetcher = new AccountAvatarFetcher(
form_->icon_url, weak_ptr_factory_.GetWeakPtr());
fetcher->Start(request_context);
}
AddChildView(image_view_);
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
if (!upper_text.empty()) {
upper_label_ = new views::Label(
upper_text, rb->GetFontList(ui::ResourceBundle::BoldFont));
upper_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
AddChildView(upper_label_);
}
if (!lower_text.empty()) {
lower_label_ = new views::Label(
lower_text, rb->GetFontList(ui::ResourceBundle::SmallFont));
lower_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
AddChildView(lower_label_);
}
SetFocusable(true);
}
CredentialsItemView::~CredentialsItemView() = default;
void CredentialsItemView::UpdateAvatar(const gfx::ImageSkia& image) {
image_view_->SetImage(ScaleImageForAccountAvatar(image));
}
int CredentialsItemView::GetLabelOffset() const {
return GetInsets().left() + image_view_->GetPreferredSize().width() +
kSpacing;
}
gfx::Size CredentialsItemView::GetPreferredSize() const {
gfx::Size labels_size = GetTextLabelsSize(upper_label_, lower_label_);
gfx::Size size = gfx::Size(kAvatarImageSize + labels_size.width(),
std::max(kAvatarImageSize, labels_size.height()));
const gfx::Insets insets(GetInsets());
size.Enlarge(insets.width(), insets.height());
size.Enlarge(kSpacing, 0);
// Make the size at least as large as the minimum size needed by the border.
size.SetToMax(border() ? border()->GetMinimumSize() : gfx::Size());
return size;
}
int CredentialsItemView::GetHeightForWidth(int w) const {
return View::GetHeightForWidth(w);
}
void CredentialsItemView::Layout() {
gfx::Rect child_area(GetChildAreaBounds());
child_area.Inset(GetInsets());
gfx::Size image_size(image_view_->GetPreferredSize());
image_size.SetToMin(child_area.size());
gfx::Point image_origin(child_area.origin());
image_origin.Offset(0, (child_area.height() - image_size.height()) / 2);
image_view_->SetBoundsRect(gfx::Rect(image_origin, image_size));
gfx::Size upper_size =
upper_label_ ? upper_label_->GetPreferredSize() : gfx::Size();
gfx::Size lower_size =
lower_label_ ? lower_label_->GetPreferredSize() : gfx::Size();
int y_offset = (child_area.height() -
(upper_size.height() + lower_size.height())) / 2;
gfx::Point label_origin(image_origin.x() + image_size.width() + kSpacing,
child_area.origin().y() + y_offset);
if (upper_label_)
upper_label_->SetBoundsRect(gfx::Rect(label_origin, upper_size));
if (lower_label_) {
label_origin.Offset(0, upper_size.height());
lower_label_->SetBoundsRect(gfx::Rect(label_origin, lower_size));
}
}