1 // Copyright 2015 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 #import "chrome/browser/ui/cocoa/passwords/manage_credential_item_view_controller.h"
9 #include "base/i18n/rtl.h"
10 #include "chrome/browser/ui/chrome_style.h"
11 #import "chrome/browser/ui/cocoa/passwords/credential_item_view.h"
12 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
13 #include "components/password_manager/core/common/password_manager_ui.h"
14 #include "grit/components_strings.h"
15 #include "grit/generated_resources.h"
16 #include "skia/ext/skia_utils_mac.h"
17 #import "ui/base/cocoa/controls/hyperlink_button_cell.h"
18 #import "ui/base/cocoa/hover_image_button.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/base/resource/resource_bundle.h"
21 #include "ui/gfx/image/image.h"
22 #include "ui/resources/grit/ui_resources.h"
26 // Horizontal space betweeen subviews of a credential item.
27 const CGFloat kItemSubviewsHorizontalSpacing = 20.0f;
29 // Lays out |leftSubview| and |rightSubview| within |item| so that they stick
30 // to the left and right sides of |item|, respectively, and resizes |item| to
31 // hold them. Flipped in RTL.
32 void LayOutItem(NSView* item, NSView* leftSubview, NSView* rightSubview) {
33 const CGFloat width = NSWidth([leftSubview frame]) +
34 kItemSubviewsHorizontalSpacing +
35 NSWidth([rightSubview frame]);
36 const CGFloat height =
37 std::max(NSHeight([leftSubview frame]), NSHeight([rightSubview frame]));
38 [item setFrameSize:NSMakeSize(width, height)];
40 setFrameOrigin:NSMakePoint(base::i18n::IsRTL()
41 ? width - NSWidth([leftSubview frame])
45 setFrameOrigin:NSMakePoint(
48 : width - NSWidth([rightSubview frame]),
49 (height - NSHeight([rightSubview frame])) / 2.0f)];
50 [leftSubview setAutoresizingMask:NSViewWidthSizable |
51 (base::i18n::IsRTL() ? NSViewMinXMargin
53 [rightSubview setAutoresizingMask:(base::i18n::IsRTL() ? NSViewMaxXMargin
58 @implementation ManageCredentialItemView : NSView
60 - (id)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
61 delegate:(id<CredentialItemDelegate>)delegate
64 if ((self = [super initWithFrame:NSZeroRect])) {
66 // ----------------------------------------------
67 // | | John Q. Facebooker | |
68 // | icon | john@somewhere.com | X |
70 // ----------------------------------------------
73 credentialItem_.reset([[CredentialItemView alloc]
74 initWithPasswordForm:passwordForm
75 credentialType:password_manager::CredentialType::
76 CREDENTIAL_TYPE_PASSWORD
77 style:password_manager_mac::CredentialItemStyle::
80 [self addSubview:credentialItem_];
82 deleteButton_.reset([[HoverImageButton alloc]
83 initWithFrame:NSMakeRect(0, 0, chrome_style::GetCloseButtonSize(),
84 chrome_style::GetCloseButtonSize())]);
85 [deleteButton_ setBordered:NO];
86 [[deleteButton_ cell] setHighlightsBy:NSNoCellMask];
87 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
89 setDefaultImage:bundle.GetNativeImageNamed(IDR_CLOSE_2).ToNSImage()];
91 setHoverImage:bundle.GetNativeImageNamed(IDR_CLOSE_2_H).ToNSImage()];
93 setPressedImage:bundle.GetNativeImageNamed(IDR_CLOSE_2_P).ToNSImage()];
94 [deleteButton_ setTarget:target];
95 [deleteButton_ setAction:action];
96 [self addSubview:deleteButton_];
98 LayOutItem(self, credentialItem_, deleteButton_);
105 @implementation DeletedCredentialItemView : NSView
106 - (id)initWithTarget:(id)target action:(SEL)action {
107 if ((self = [super initWithFrame:NSZeroRect])) {
109 // ----------------------------------------------
110 // | Such-and-such has been deleted. [Undo]
111 // ----------------------------------------------
114 base::scoped_nsobject<NSTextField> explanationLabel(
115 [[NSTextField alloc] initWithFrame:NSZeroRect]);
117 setStringValue:l10n_util::GetNSString(IDS_MANAGE_PASSWORDS_DELETED)];
118 NSFont* font = ResourceBundle::GetSharedInstance()
119 .GetFontList(ResourceBundle::SmallFont)
122 [explanationLabel setFont:font];
123 [explanationLabel setEditable:NO];
124 [explanationLabel setSelectable:NO];
125 [explanationLabel setDrawsBackground:NO];
126 [explanationLabel setBezeled:NO];
127 [explanationLabel sizeToFit];
128 [self addSubview:explanationLabel];
130 undoButton_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
131 base::scoped_nsobject<HyperlinkButtonCell> cell([[HyperlinkButtonCell alloc]
132 initTextCell:l10n_util::GetNSString(IDS_MANAGE_PASSWORDS_UNDO)]);
133 [cell setControlSize:NSSmallControlSize];
134 [cell setShouldUnderline:NO];
135 [cell setUnderlineOnHover:NO];
136 [cell setTextColor:gfx::SkColorToCalibratedNSColor(
137 chrome_style::GetLinkColor())];
138 [undoButton_ setCell:cell.get()];
139 [undoButton_ sizeToFit];
140 [undoButton_ setTarget:target];
141 [undoButton_ setAction:action];
142 [self addSubview:undoButton_];
144 LayOutItem(self, explanationLabel, undoButton_);
151 @interface ManageCredentialItemViewController()
152 - (void)deleteCredential:(id)sender;
153 - (void)undoDelete:(id)sender;
156 @implementation ManageCredentialItemViewController
157 - (id)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm
158 model:(ManagePasswordsBubbleModel*)model
159 delegate:(id<CredentialItemDelegate>)delegate {
160 if ((self = [super initWithNibName:nil bundle:nil])) {
161 passwordForm_ = passwordForm;
163 delegate_ = delegate;
164 [self changeToManageView];
169 - (void)performLayout {
170 [self view].subviews = @[ contentView_ ];
171 [[self view] setFrameSize:[contentView_ frame].size];
172 [contentView_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
176 [self setView:[[[NSView alloc] initWithFrame:NSZeroRect] autorelease]];
177 [self performLayout];
180 - (void)deleteCredential:(id)sender {
181 model_->OnPasswordAction(passwordForm_,
182 ManagePasswordsBubbleModel::REMOVE_PASSWORD);
183 [self changeToDeletedView];
184 [self performLayout];
187 - (void)undoDelete:(id)sender {
188 model_->OnPasswordAction(passwordForm_,
189 ManagePasswordsBubbleModel::ADD_PASSWORD);
190 [self changeToManageView];
191 [self performLayout];
194 - (void)changeToManageView {
195 contentView_.reset([[ManageCredentialItemView alloc]
196 initWithPasswordForm:passwordForm_
199 action:@selector(deleteCredential:)]);
202 - (void)changeToDeletedView {
203 contentView_.reset([[DeletedCredentialItemView alloc]
205 action:@selector(undoDelete:)]);
209 @implementation ManageCredentialItemViewController (Testing)
211 - (const autofill::PasswordForm&)passwordForm {
212 return passwordForm_;
215 - (NSView*)contentView {
216 return contentView_.get();