1 // Copyright 2013 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/manage_password_item_view.h"
7 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
8 #include "chrome/grit/generated_resources.h"
9 #include "ui/base/l10n/l10n_util.h"
10 #include "ui/base/resource/resource_bundle.h"
11 #include "ui/resources/grit/ui_resources.h"
12 #include "ui/views/border.h"
13 #include "ui/views/controls/button/button.h"
14 #include "ui/views/controls/button/image_button.h"
15 #include "ui/views/controls/label.h"
16 #include "ui/views/controls/link.h"
17 #include "ui/views/controls/link_listener.h"
18 #include "ui/views/layout/fill_layout.h"
19 #include "ui/views/layout/grid_layout.h"
20 #include "ui/views/layout/layout_constants.h"
29 void BuildColumnSet(views::GridLayout* layout, int column_set_id) {
30 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
32 // The username/"Deleted!" field.
33 column_set->AddPaddingColumn(0, views::kItemLabelSpacing);
34 column_set->AddColumn(views::GridLayout::FILL,
35 views::GridLayout::FILL,
37 views::GridLayout::USE_PREF,
41 // The password/"Undo!" field.
42 column_set->AddPaddingColumn(0, views::kItemLabelSpacing);
43 column_set->AddColumn(views::GridLayout::FILL,
44 views::GridLayout::FILL,
46 views::GridLayout::USE_PREF,
50 // If we're in manage-mode, we need another column for the delete button.
51 if (column_set_id == THREE_COLUMN_SET) {
52 column_set->AddPaddingColumn(0, views::kItemLabelSpacing);
53 column_set->AddColumn(views::GridLayout::TRAILING,
54 views::GridLayout::FILL,
56 views::GridLayout::USE_PREF,
60 column_set->AddPaddingColumn(0, views::kItemLabelSpacing);
63 views::Label* GenerateUsernameLabel(const autofill::PasswordForm& form) {
64 views::Label* label = new views::Label(form.username_value);
65 label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
66 ui::ResourceBundle::SmallFont));
67 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
71 views::Label* GeneratePasswordLabel(const autofill::PasswordForm& form) {
72 views::Label* label = new views::Label(form.password_value);
73 label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
74 ui::ResourceBundle::SmallFont));
75 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
76 label->SetObscured(true);
82 // Render credentials in two columns: username and password.
83 class ManagePasswordItemView::PendingView : public views::View {
85 explicit PendingView(ManagePasswordItemView* parent);
88 virtual ~PendingView();
91 ManagePasswordItemView::PendingView::PendingView(
92 ManagePasswordItemView* parent) {
93 views::GridLayout* layout = new views::GridLayout(this);
94 SetLayoutManager(layout);
96 BuildColumnSet(layout, TWO_COLUMN_SET);
97 layout->StartRowWithPadding(
98 0, TWO_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
99 layout->AddView(GenerateUsernameLabel(parent->password_form_));
100 layout->AddView(GeneratePasswordLabel(parent->password_form_));
101 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
104 ManagePasswordItemView::PendingView::~PendingView() {
107 // Render credentials in three columns: username, password, and delete.
108 class ManagePasswordItemView::ManageView : public views::View,
109 public views::ButtonListener {
111 explicit ManageView(ManagePasswordItemView* parent);
114 virtual ~ManageView();
116 // views::ButtonListener:
117 virtual void ButtonPressed(views::Button* sender,
118 const ui::Event& event) OVERRIDE;
120 views::ImageButton* delete_button_;
121 ManagePasswordItemView* parent_;
124 ManagePasswordItemView::ManageView::ManageView(ManagePasswordItemView* parent)
126 views::GridLayout* layout = new views::GridLayout(this);
127 SetLayoutManager(layout);
129 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
130 delete_button_ = new views::ImageButton(this);
131 delete_button_->SetImage(views::ImageButton::STATE_NORMAL,
132 rb->GetImageNamed(IDR_CLOSE_2).ToImageSkia());
133 delete_button_->SetImage(views::ImageButton::STATE_HOVERED,
134 rb->GetImageNamed(IDR_CLOSE_2_H).ToImageSkia());
135 delete_button_->SetImage(views::ImageButton::STATE_PRESSED,
136 rb->GetImageNamed(IDR_CLOSE_2_P).ToImageSkia());
138 BuildColumnSet(layout, THREE_COLUMN_SET);
139 layout->StartRowWithPadding(
140 0, THREE_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
141 layout->AddView(GenerateUsernameLabel(parent->password_form_));
142 layout->AddView(GeneratePasswordLabel(parent->password_form_));
143 layout->AddView(delete_button_);
144 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
147 ManagePasswordItemView::ManageView::~ManageView() {
150 void ManagePasswordItemView::ManageView::ButtonPressed(views::Button* sender,
151 const ui::Event& event) {
152 DCHECK_EQ(delete_button_, sender);
153 parent_->NotifyClickedDelete();
156 // Render a notification to the user that a password has been removed, and
157 // offer an undo link.
158 class ManagePasswordItemView::UndoView : public views::View,
159 public views::LinkListener {
161 explicit UndoView(ManagePasswordItemView* parent);
166 // views::LinkListener:
167 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
169 views::Link* undo_link_;
170 ManagePasswordItemView* parent_;
173 ManagePasswordItemView::UndoView::UndoView(ManagePasswordItemView* parent)
175 views::GridLayout* layout = new views::GridLayout(this);
176 SetLayoutManager(layout);
179 new views::Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED));
180 text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
181 text->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
182 ui::ResourceBundle::SmallFont));
185 new views::Link(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_UNDO));
186 undo_link_->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
187 undo_link_->set_listener(this);
188 undo_link_->SetUnderline(false);
189 undo_link_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
190 ui::ResourceBundle::SmallFont));
192 BuildColumnSet(layout, TWO_COLUMN_SET);
193 layout->StartRowWithPadding(
194 0, TWO_COLUMN_SET, 0, views::kRelatedControlVerticalSpacing);
195 layout->AddView(text);
196 layout->AddView(undo_link_);
197 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
200 ManagePasswordItemView::UndoView::~UndoView() {
203 void ManagePasswordItemView::UndoView::LinkClicked(views::Link* sender,
205 DCHECK_EQ(undo_link_, sender);
206 parent_->NotifyClickedUndo();
209 // ManagePasswordItemView
210 ManagePasswordItemView::ManagePasswordItemView(
211 ManagePasswordsBubbleModel* manage_passwords_bubble_model,
212 const autofill::PasswordForm& password_form,
213 password_manager::ui::PasswordItemPosition position)
214 : model_(manage_passwords_bubble_model),
215 password_form_(password_form),
216 delete_password_(false) {
217 views::FillLayout* layout = new views::FillLayout();
218 SetLayoutManager(layout);
220 // When a password is displayed as the first item in a list, it has borders
221 // on both the top and bottom. When it's in the middle of a list, or at the
222 // end, it has a border only on the bottom.
223 SetBorder(views::Border::CreateSolidSidedBorder(
224 position == password_manager::ui::FIRST_ITEM ? 1 : 0,
228 GetNativeTheme()->GetSystemColor(
229 ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor)));
231 if (password_manager::ui::IsPendingState(model_->state())) {
232 AddChildView(new PendingView(this));
234 AddChildView(new ManageView(this));
236 GetLayoutManager()->Layout(this);
239 ManagePasswordItemView::~ManagePasswordItemView() {
242 void ManagePasswordItemView::NotifyClickedDelete() {
243 delete_password_ = true;
247 void ManagePasswordItemView::NotifyClickedUndo() {
248 delete_password_ = false;
252 void ManagePasswordItemView::Refresh() {
253 DCHECK(!password_manager::ui::IsPendingState(model_->state()));
255 RemoveAllChildViews(true);
256 if (delete_password_)
257 AddChildView(new UndoView(this));
259 AddChildView(new ManageView(this));
260 GetLayoutManager()->Layout(this);
262 // After the view is consistent, notify the model that the password needs to
263 // be updated (either removed or put back into the store, as appropriate.
264 model_->OnPasswordAction(password_form_,
266 ? ManagePasswordsBubbleModel::REMOVE_PASSWORD
267 : ManagePasswordsBubbleModel::ADD_PASSWORD);