Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6353)

Unified Diff: chrome/browser/ui/cocoa/passwords/manage_passwords_bubble_manage_view_controller.mm

Issue 462563002: Add ManagePasswordsBubbleManageViewController and unit tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix views Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/passwords/manage_passwords_bubble_manage_view_controller.mm
diff --git a/chrome/browser/ui/cocoa/passwords/manage_passwords_bubble_manage_view_controller.mm b/chrome/browser/ui/cocoa/passwords/manage_passwords_bubble_manage_view_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..4d4095366901af2eabd3a4a531f3bc9010db22db
--- /dev/null
+++ b/chrome/browser/ui/cocoa/passwords/manage_passwords_bubble_manage_view_controller.mm
@@ -0,0 +1,213 @@
+// 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.
+
+#import "chrome/browser/ui/cocoa/passwords/manage_passwords_bubble_manage_view_controller.h"
+
+#include <cmath>
+
+#include "base/strings/sys_string_conversions.h"
+#include "chrome/browser/ui/chrome_style.h"
+#import "chrome/browser/ui/cocoa/passwords/manage_password_item_view_controller.h"
+#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
+#include "grit/generated_resources.h"
+#include "skia/ext/skia_utils_mac.h"
+#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#import "ui/base/cocoa/controls/hyperlink_button_cell.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using namespace password_manager::mac::ui;
+
+@implementation PasswordItemListView
+- (id)initWithModel:(ManagePasswordsBubbleModel*)model {
+ if ((self = [super initWithFrame:NSZeroRect])) {
+ base::scoped_nsobject<NSMutableArray> items([[NSMutableArray alloc] init]);
+
+ // Create and lay out the items.
+ const CGFloat curX = 0;
+ CGFloat maxX = 0;
+ CGFloat curY = 0;
+ for (autofill::ConstPasswordFormMap::const_reverse_iterator i =
+ model->best_matches().rbegin();
+ i != model->best_matches().rend();
+ ++i) {
+ autofill::PasswordForm form = *i->second;
+ password_manager::ui::PasswordItemPosition position =
+ (&(*i) == &(*model->best_matches().begin()))
+ ? password_manager::ui::FIRST_ITEM
+ : password_manager::ui::SUBSEQUENT_ITEM;
+ base::scoped_nsobject<ManagePasswordItemViewController> item(
+ [[ManagePasswordItemViewController alloc] initWithModel:model
+ passwordForm:form
+ position:position]);
+ [items addObject:item.get()];
+ NSView* itemView = [item view];
+ [self addSubview:itemView];
+
+ // The items stack up on each other.
+ [itemView setFrameOrigin:NSMakePoint(curX, curY)];
+ maxX = NSMaxX([itemView frame]);
+ curY = NSMaxY([itemView frame]);
+ }
+ [self setFrameSize:NSMakeSize(maxX, curY)];
+ itemViews_.reset(items.release());
+ }
+ return self;
+}
+@end
+
+@implementation PasswordItemListView (Testing)
+- (NSArray*)itemViews {
+ return itemViews_.get();
+}
+@end
+
+@implementation NoPasswordsView
+- (id)initWithWidth:(CGFloat)width {
+ if ((self = [super initWithFrame:NSZeroRect])) {
+ [self setEditable:NO];
+ [self setSelectable:NO];
+ [self setDrawsBackground:NO];
+ [self setBezeled:NO];
+ [self setStringValue:l10n_util::GetNSString(
+ IDS_MANAGE_PASSWORDS_NO_PASSWORDS)];
+ [self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+ [[self cell] setWraps:YES];
+ [self setFrameSize:NSMakeSize(width, MAXFLOAT)];
+ [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:self];
+ }
+ return self;
+}
+@end
+
+@interface ManagePasswordsBubbleManageViewController ()
+- (void)onDoneClicked:(id)sender;
+- (void)onManageClicked:(id)sender;
+@end
+
+@implementation ManagePasswordsBubbleManageViewController
+
+- (id)initWithModel:(ManagePasswordsBubbleModel*)model
+ delegate:(id<ManagePasswordsBubbleContentViewDelegate>)delegate {
+ if ((self = [super initWithNibName:nil bundle:nil])) {
+ model_ = model;
+ delegate_ = delegate;
+ }
+ return self;
+}
+
+- (void)loadView {
+ self.view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease];
+
+ // -----------------------------------
+ // | Title |
+ // | ----------------------------- | (1 px border)
+ // | username password x |
+ // | ----------------------------- | (1 px border)
+ // | username password x |
+ // | ----------------------------- | (1 px border)
+ // | username password x |
+ // | ----------------------------- | (1 px border)
+ // | Manage [Done] |
+ // -----------------------------------
+
+ // The bubble should be wide enough to fit the title row, the username and
+ // password rows, and the buttons row on one line each, but not smaller than
+ // kDesiredBubbleWidth.
+
+ // Create the elements and add them to the view.
+ NSTextField* titleLabel =
+ [self addTitleLabel:base::SysUTF16ToNSString(model_->title())];
+
+ // Content. If we have a list of passwords to store for the current site, we
+ // display them to the user for management. Otherwise, we show a "No passwords
+ // for this site" message.
+ if (model_->best_matches().empty()) {
+ const CGFloat noPasswordsWidth = std::max(
+ kDesiredBubbleWidth - 2 * kFramePadding, NSWidth([titleLabel frame]));
+ contentView_.reset(
+ [[NoPasswordsView alloc] initWithWidth:noPasswordsWidth]);
+ } else {
+ contentView_.reset(
+ [[PasswordItemListView alloc] initWithModel:model_]);
+ }
+ [self.view addSubview:contentView_];
+ DCHECK_GE(NSWidth([contentView_ frame]), NSWidth([titleLabel frame]));
+
+ // Done button.
+ doneButton_.reset([[self addButton:l10n_util::GetNSString(IDS_DONE)
+ target:self
+ action:@selector(onDoneClicked:)] retain]);
+
+ // Manage button.
+ manageButton_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
+ base::scoped_nsobject<HyperlinkButtonCell> cell([[HyperlinkButtonCell alloc]
+ initTextCell:base::SysUTF16ToNSString(model_->manage_link())]);
+ [cell setControlSize:NSSmallControlSize];
+ [cell setShouldUnderline:NO];
+ [cell setUnderlineOnHover:NO];
+ [cell setTextColor:gfx::SkColorToCalibratedNSColor(
+ chrome_style::GetLinkColor())];
+ [manageButton_ setCell:cell.get()];
+ [manageButton_ sizeToFit];
+ [manageButton_ setTarget:self];
+ [manageButton_ setAction:@selector(onManageClicked:)];
+ [self.view addSubview:manageButton_];
+
+ // Layout the elements, starting at the bottom and moving up.
+
+ // The Done button goes in the bottom-right corner.
+ const CGFloat width = 2 * kFramePadding + NSWidth([contentView_ frame]);
+ CGFloat curX = width - kFramePadding - NSWidth([doneButton_ frame]);
+ CGFloat curY = kFramePadding;
+ [doneButton_ setFrameOrigin:NSMakePoint(curX, curY)];
+
+ // The Manage button goes in the bottom-left corner, centered vertically with
+ // the Done button.
+ curX = kFramePadding;
+ const CGFloat diffY = std::ceil(
+ (NSHeight([doneButton_ frame]) - NSHeight([manageButton_ frame])) / 2.0);
+ [manageButton_ setFrameOrigin:NSMakePoint(curX, curY + diffY)];
+
+ // The content goes above the button row.
+ curX = kFramePadding;
+ curY = NSMaxY([doneButton_ frame]) + kUnrelatedControlVerticalPadding;
+ [contentView_ setFrameOrigin:NSMakePoint(curX, curY)];
+
+ // The title goes above the content.
+ curY = NSMaxY([contentView_ frame]) + kUnrelatedControlVerticalPadding;
+ [titleLabel setFrameOrigin:NSMakePoint(curX, curY)];
+
+ curX = NSMaxX([contentView_ frame]) + kFramePadding;
+ curY = NSMaxY([titleLabel frame]) + kFramePadding;
+ DCHECK_EQ(width, curX);
+ [self.view setFrameSize:NSMakeSize(curX, curY)];
+}
+
+- (void)onDoneClicked:(id)sender {
+ model_->OnDoneClicked();
+ [delegate_ viewShouldDismiss];
+}
+
+- (void)onManageClicked:(id)sender {
+ model_->OnManageLinkClicked();
+ [delegate_ viewShouldDismiss];
+}
+
+@end
+
+@implementation ManagePasswordsBubbleManageViewController (Testing)
+
+- (NSButton*)doneButton {
+ return doneButton_.get();
+}
+
+- (NSButton*)manageButton {
+ return manageButton_.get();
+}
+
+- (NSView*)contentView {
+ return contentView_.get();
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698