Index: chrome/browser/ui/cocoa/passwords/manage_password_item_view_controller.mm |
diff --git a/chrome/browser/ui/cocoa/passwords/manage_password_item_view_controller.mm b/chrome/browser/ui/cocoa/passwords/manage_password_item_view_controller.mm |
index e856750c7367ab79a0eb0bba817fb9a435e1affb..b7d83a29efd5e7bf6ca1f1737350777f670ee6f9 100644 |
--- a/chrome/browser/ui/cocoa/passwords/manage_password_item_view_controller.mm |
+++ b/chrome/browser/ui/cocoa/passwords/manage_password_item_view_controller.mm |
@@ -4,12 +4,16 @@ |
#import "chrome/browser/ui/cocoa/passwords/manage_password_item_view_controller.h" |
+#include <utility> |
+ |
#include "base/logging.h" |
+#include "base/mac/foundation_util.h" |
#include "base/strings/string16.h" |
#include "base/strings/sys_string_conversions.h" |
#include "base/strings/utf_string_conversions.h" |
#include "chrome/browser/ui/chrome_style.h" |
#import "chrome/browser/ui/cocoa/passwords/manage_passwords_bubble_content_view_controller.h" |
+#import "chrome/browser/ui/cocoa/passwords/password_item_views.h" |
#include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" |
#include "grit/components_strings.h" |
#include "grit/generated_resources.h" |
@@ -24,15 +28,10 @@ using namespace password_manager::mac::ui; |
namespace { |
-const SkColor kHoverColor = SkColorSetARGBInline(0xFF, 0xEB, 0xEB, 0xEB); |
- |
// Constants shared with toolkit-views layout_constants.h. |
const CGFloat kItemLabelSpacing = 10; |
const CGFloat kRelatedControlVerticalSpacing = 8; |
- |
-NSColor* HoverColor() { |
- return gfx::SkColorToCalibratedNSColor(kHoverColor); |
-} |
+const CGFloat kDesiredRowWidth = kDesiredBubbleWidth - 2 * kFramePadding; |
NSFont* LabelFont() { |
return [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; |
@@ -43,32 +42,29 @@ NSSize LabelSize(int resourceID) { |
sizeWithAttributes:@{NSFontAttributeName : LabelFont()}]; |
} |
-CGFloat FirstFieldWidth() { |
- const CGFloat undoExplanationWidth = |
- LabelSize(IDS_MANAGE_PASSWORDS_DELETED).width; |
- const CGFloat kUsernameWidth = |
- ManagePasswordsBubbleModel::UsernameFieldWidth(); |
- const CGFloat width = std::max(kUsernameWidth, undoExplanationWidth); |
- return width; |
-} |
- |
-CGFloat SecondFieldWidth() { |
- const CGFloat undoLinkWidth = |
- LabelSize(IDS_MANAGE_PASSWORDS_UNDO).width; |
- const CGFloat kPasswordWidth = |
- ManagePasswordsBubbleModel::PasswordFieldWidth(); |
- const CGFloat width = std::max(kPasswordWidth, undoLinkWidth); |
- return width; |
+std::pair<CGFloat, CGFloat> GetResizedColumns( |
+ CGFloat maxWidth, std::pair<CGFloat, CGFloat> columnsWidth) { |
+ // Free space can be negative. |
+ CGFloat freeSpace = |
+ maxWidth - (columnsWidth.first + columnsWidth.second + kItemLabelSpacing); |
+ if (freeSpace >= 0) { |
+ return std::make_pair(columnsWidth.first + freeSpace / 2, |
+ columnsWidth.second + freeSpace / 2); |
+ } |
+ // Make sure that the sizes are nonnegative. |
+ CGFloat firstColumnPercent = |
+ columnsWidth.first / (columnsWidth.first + columnsWidth.second); |
+ return std::make_pair( |
+ columnsWidth.first + freeSpace * firstColumnPercent, |
+ columnsWidth.second + freeSpace * (1 - firstColumnPercent)); |
} |
-CGFloat ItemWidth() { |
- const CGFloat width = |
- FirstFieldWidth() + |
- kItemLabelSpacing + |
- SecondFieldWidth() + |
- kItemLabelSpacing + |
- chrome_style::GetCloseButtonSize(); |
- return width; |
+CGFloat ManagePasswordItemWidth() { |
+ const CGFloat undoExplanationWidth = |
+ LabelSize(IDS_MANAGE_PASSWORDS_DELETED).width; |
+ const CGFloat undoLinkWidth = LabelSize(IDS_MANAGE_PASSWORDS_UNDO).width; |
+ return std::max(kDesiredRowWidth, |
+ undoExplanationWidth + kItemLabelSpacing + undoLinkWidth); |
} |
void InitLabel(NSTextField* textField, const base::string16& text) { |
@@ -78,6 +74,7 @@ void InitLabel(NSTextField* textField, const base::string16& text) { |
[textField setDrawsBackground:NO]; |
[textField setBezeled:NO]; |
[textField setFont:LabelFont()]; |
+ [[textField cell] setLineBreakMode:NSLineBreakByTruncatingTail]; |
[textField sizeToFit]; |
} |
@@ -89,37 +86,29 @@ NSTextField* Label(const base::string16& text) { |
} |
NSTextField* UsernameLabel(const base::string16& text) { |
- NSTextField* textField = Label(text); |
- [textField |
- setFrameSize:NSMakeSize(FirstFieldWidth(), NSHeight([textField frame]))]; |
- return textField; |
+ return Label(text); |
} |
NSSecureTextField* PasswordLabel(const base::string16& text) { |
base::scoped_nsobject<NSSecureTextField> textField( |
[[NSSecureTextField alloc] initWithFrame:NSZeroRect]); |
InitLabel(textField, text); |
- [textField |
- setFrameSize:NSMakeSize(SecondFieldWidth(), NSHeight([textField frame]))]; |
return textField.autorelease(); |
} |
NSTextField* FederationLabel(const base::string16& text) { |
- NSTextField* textField = Label(text); |
- [textField |
- setFrameSize:NSMakeSize(SecondFieldWidth(), NSHeight([textField frame]))]; |
- return textField; |
+ return Label(text); |
} |
base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
- return form.username_value.empty() ? |
- l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN) : |
- form.username_value; |
+ return form.username_value.empty() |
+ ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN) |
+ : form.username_value; |
} |
} // namespace |
-@implementation ManagePasswordItemUndoView |
+@implementation UndoPasswordItemView |
- (id)initWithTarget:(id)target action:(SEL)action { |
if ((self = [super init])) { |
// The button should look like a link. |
@@ -130,46 +119,58 @@ base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
[cell setShouldUnderline:NO]; |
[cell setUnderlineOnHover:NO]; |
[cell setTextColor:gfx::SkColorToCalibratedNSColor( |
- chrome_style::GetLinkColor())]; |
+ chrome_style::GetLinkColor())]; |
[undoButton_ setCell:cell.get()]; |
[undoButton_ sizeToFit]; |
[undoButton_ setTarget:target]; |
[undoButton_ setAction:action]; |
- |
- const CGFloat width = ItemWidth(); |
- CGFloat curX = 0; |
- CGFloat curY = kRelatedControlVerticalSpacing; |
+ [self addSubview:undoButton_]; |
// Add the explanation text. |
- NSTextField* label = |
- Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED)); |
- [label setFrameOrigin:NSMakePoint(curX, curY)]; |
- [self addSubview:label]; |
- |
- // The undo button should be right-aligned. |
- curX = width - NSWidth([undoButton_ frame]); |
- [undoButton_ setFrameOrigin:NSMakePoint(curX, curY)]; |
- [self addSubview:undoButton_ ]; |
- |
- // Move to the top-right of the delete button. |
- curX = NSMaxX([undoButton_ frame]); |
- curY = NSMaxY([undoButton_ frame]) + kRelatedControlVerticalSpacing; |
- |
- // Update the frame. |
- DCHECK_EQ(width, curX); |
- [self setFrameSize:NSMakeSize(curX, curY)]; |
+ label_.reset([Label(l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_DELETED)) |
+ retain]); |
+ [self addSubview:label_]; |
} |
return self; |
} |
+ |
+#pragma mark PasswordItemTwoColumnView |
+ |
+- (void)layoutWithFirstColumn:(CGFloat)firstWidth |
+ secondColumn:(CGFloat)secondWidth { |
+ const CGFloat width = ManagePasswordItemWidth(); |
+ CGFloat curX = 0; |
+ CGFloat curY = kRelatedControlVerticalSpacing; |
+ [label_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ // The undo button should be right-aligned. |
+ curX = width - NSWidth([undoButton_ frame]); |
+ [undoButton_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ // Move to the top-right of the delete button. |
+ curX = NSMaxX([undoButton_ frame]); |
+ curY = NSMaxY([undoButton_ frame]) + kRelatedControlVerticalSpacing; |
+ |
+ // Update the frame. |
+ [self setFrameSize:NSMakeSize(curX, curY)]; |
+} |
+ |
+- (CGFloat)firstColumnWidth { |
+ // This view doesn't have columns aligned with username/password. |
+ return 0; |
+} |
+ |
+- (CGFloat)secondColumnWidth { |
+ // This view doesn't have columns aligned with username/password. |
+ return 0; |
+} |
@end |
-@implementation ManagePasswordItemUndoView (Testing) |
+@implementation UndoPasswordItemView (Testing) |
- (NSButton*)undoButton { |
return undoButton_.get(); |
} |
@end |
-@implementation ManagePasswordItemManageView |
+@implementation ManagePasswordItemView |
- (id)initWithForm:(const autofill::PasswordForm&)form |
target:(id)target |
action:(SEL)action { |
@@ -188,44 +189,68 @@ base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
setPressedImage:bundle.GetImageNamed(IDR_CLOSE_2_P).ToNSImage()]; |
[deleteButton_ setTarget:target]; |
[deleteButton_ setAction:action]; |
- |
- const CGFloat width = ItemWidth(); |
- CGFloat curX = 0; |
- CGFloat curY = kRelatedControlVerticalSpacing; |
+ [self addSubview:deleteButton_]; |
// Add the username. |
usernameField_.reset([UsernameLabel(GetDisplayUsername(form)) retain]); |
- [usernameField_ setFrameOrigin:NSMakePoint(curX, curY)]; |
[self addSubview:usernameField_]; |
- // Move to the right of the username and add the password. |
- curX = NSMaxX([usernameField_ frame]) + kItemLabelSpacing; |
- passwordField_.reset([PasswordLabel(form.password_value) retain]); |
- [passwordField_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ if (form.federation_url.is_empty()) { |
+ passwordField_.reset([PasswordLabel(form.password_value) retain]); |
+ } else { |
+ base::string16 text = l10n_util::GetStringFUTF16( |
+ IDS_PASSWORDS_VIA_FEDERATION, |
+ base::UTF8ToUTF16(form.federation_url.host())); |
+ passwordField_.reset([FederationLabel(text) retain]); |
+ } |
[self addSubview:passwordField_]; |
+ } |
+ return self; |
+} |
- // The delete button should be right-aligned. |
- curX = width - NSWidth([deleteButton_ frame]); |
- [deleteButton_ setFrameOrigin:NSMakePoint(curX, curY)]; |
- [self addSubview:deleteButton_]; |
+#pragma mark PasswordItemTwoColumnView |
- // Move to the top-right of the delete button. |
- curX = NSMaxX([deleteButton_ frame]); |
- curY = NSMaxY([deleteButton_ frame]) + kRelatedControlVerticalSpacing; |
+- (void)layoutWithFirstColumn:(CGFloat)firstWidth |
+ secondColumn:(CGFloat)secondWidth { |
+ const CGFloat width = ManagePasswordItemWidth(); |
+ std::pair<CGFloat, CGFloat> sizes = GetResizedColumns( |
+ width - NSWidth([deleteButton_ frame]) - kRelatedControlVerticalSpacing, |
+ std::make_pair(firstWidth, secondWidth)); |
+ [usernameField_ |
+ setFrameSize:NSMakeSize(sizes.first, NSHeight([usernameField_ frame]))]; |
+ [passwordField_ |
+ setFrameSize:NSMakeSize(sizes.second, NSHeight([passwordField_ frame]))]; |
+ CGFloat curX = 0; |
+ CGFloat curY = kRelatedControlVerticalSpacing; |
+ [usernameField_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ // Move to the right of the username and add the password. |
+ curX = NSMaxX([usernameField_ frame]) + kItemLabelSpacing; |
+ [passwordField_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ // The delete button should be right-aligned. |
+ curX = width - NSWidth([deleteButton_ frame]); |
+ [deleteButton_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ // Move to the top-right of the delete button. |
+ curX = NSMaxX([deleteButton_ frame]); |
+ curY = NSMaxY([deleteButton_ frame]) + kRelatedControlVerticalSpacing; |
- // Update the frame. |
- DCHECK_EQ(width, curX); |
- [self setFrameSize:NSMakeSize(curX, curY)]; |
- } |
- return self; |
+ // Update the frame. |
+ [self setFrameSize:NSMakeSize(curX, curY)]; |
+} |
+ |
+- (CGFloat)firstColumnWidth { |
+ return NSWidth([usernameField_ frame]); |
+} |
+ |
+- (CGFloat)secondColumnWidth { |
+ return NSWidth([passwordField_ frame]); |
} |
@end |
-@implementation ManagePasswordItemManageView (Testing) |
+@implementation ManagePasswordItemView (Testing) |
- (NSTextField*)usernameField { |
return usernameField_.get(); |
} |
-- (NSSecureTextField*)passwordField { |
+- (NSTextField*)passwordField { |
return passwordField_.get(); |
} |
- (NSButton*)deleteButton { |
@@ -233,59 +258,71 @@ base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
} |
@end |
-@implementation ManagePasswordItemPendingView |
+@implementation PendingPasswordItemView |
- (id)initWithForm:(const autofill::PasswordForm&)form { |
if ((self = [super initWithFrame:NSZeroRect])) { |
- CGFloat curX = 0; |
- CGFloat curY = kRelatedControlVerticalSpacing; |
- |
// Add the username. |
usernameField_.reset([UsernameLabel(GetDisplayUsername(form)) retain]); |
- [usernameField_ setFrameOrigin:NSMakePoint(curX, curY)]; |
[self addSubview:usernameField_]; |
- // Move to the right of the username and add the password. |
- curX = NSMaxX([usernameField_ frame]) + kItemLabelSpacing; |
if (form.federation_url.is_empty()) { |
passwordField_.reset([PasswordLabel(form.password_value) retain]); |
} else { |
base::string16 text = l10n_util::GetStringFUTF16( |
IDS_PASSWORDS_VIA_FEDERATION, |
base::UTF8ToUTF16(form.federation_url.host())); |
- federationField_.reset([FederationLabel(text) retain]); |
+ passwordField_.reset([FederationLabel(text) retain]); |
} |
+ [self addSubview:passwordField_]; |
+ } |
+ return self; |
+} |
- NSTextField* secondField = |
- passwordField_ ? passwordField_.get() : federationField_.get(); |
- [secondField setFrameOrigin:NSMakePoint(curX, curY)]; |
- [self addSubview:secondField]; |
+#pragma mark PasswordItemTwoColumnView |
- // Move to the top-right of the password. |
- curY = NSMaxY([secondField frame]) + kRelatedControlVerticalSpacing; |
+- (void)layoutWithFirstColumn:(CGFloat)firstWidth |
+ secondColumn:(CGFloat)secondWidth { |
+ std::pair<CGFloat, CGFloat> sizes = GetResizedColumns( |
+ kDesiredRowWidth, |
+ std::make_pair(firstWidth, secondWidth)); |
+ [usernameField_ |
+ setFrameSize:NSMakeSize(sizes.first, NSHeight([usernameField_ frame]))]; |
+ [passwordField_ |
+ setFrameSize:NSMakeSize(sizes.second, NSHeight([passwordField_ frame]))]; |
+ CGFloat curX = 0; |
+ CGFloat curY = kRelatedControlVerticalSpacing; |
+ [usernameField_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ // Move to the right of the username and add the password. |
+ curX = NSMaxX([usernameField_ frame]) + kItemLabelSpacing; |
+ [passwordField_ setFrameOrigin:NSMakePoint(curX, curY)]; |
+ // Move to the top-right of the password. |
+ curX = NSMaxX([passwordField_ frame]); |
+ curY = NSMaxY([passwordField_ frame]) + kRelatedControlVerticalSpacing; |
- // Update the frame. |
- [self setFrameSize:NSMakeSize(ItemWidth(), curY)]; |
- } |
- return self; |
+ // Update the frame. |
+ [self setFrameSize:NSMakeSize(curX, curY)]; |
} |
+- (CGFloat)firstColumnWidth { |
+ return NSWidth([usernameField_ frame]); |
+} |
+ |
+- (CGFloat)secondColumnWidth { |
+ return NSWidth([passwordField_ frame]); |
+} |
@end |
-@implementation ManagePasswordItemPendingView (Testing) |
+@implementation PendingPasswordItemView (Testing) |
- (NSTextField*)usernameField { |
return usernameField_.get(); |
} |
-- (NSSecureTextField*)passwordField { |
+- (NSTextField*)passwordField { |
return passwordField_.get(); |
} |
-- (NSTextField*)federationField { |
- return federationField_.get(); |
-} |
- |
@end |
@interface ManagePasswordItemViewController () |
@@ -297,23 +334,20 @@ base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
// Find the next content view. |
- (void)updateContent; |
- |
-// Repaint the content. |
-- (void)layoutContent; |
@end |
@implementation ManagePasswordItemViewController |
-- (id)initWithModel:(ManagePasswordsBubbleModel*)model |
- passwordForm:(const autofill::PasswordForm&)passwordForm |
- position:(password_manager::ui::PasswordItemPosition)position { |
+- (id)initWithDelegate:(id<PasswordItemDelegate>)delegate |
+ passwordForm:(const autofill::PasswordForm*)passwordForm { |
if ((self = [super initWithNibName:nil bundle:nil])) { |
- model_ = model; |
- position_ = position; |
+ delegate_ = delegate; |
passwordForm_ = passwordForm; |
- state_ = model_->state() == password_manager::ui::PENDING_PASSWORD_STATE |
- ? MANAGE_PASSWORD_ITEM_STATE_PENDING |
- : MANAGE_PASSWORD_ITEM_STATE_MANAGE; |
+ if ([delegate_ model]->state() == |
+ password_manager::ui::PENDING_PASSWORD_STATE) |
+ state_ = MANAGE_PASSWORD_ITEM_STATE_PENDING; |
+ else |
+ state_ = MANAGE_PASSWORD_ITEM_STATE_MANAGE; |
[self updateContent]; |
} |
return self; |
@@ -323,46 +357,53 @@ base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
DCHECK_EQ(MANAGE_PASSWORD_ITEM_STATE_MANAGE, state_); |
state_ = MANAGE_PASSWORD_ITEM_STATE_DELETED; |
[self refresh]; |
- model_->OnPasswordAction(passwordForm_, |
- ManagePasswordsBubbleModel::REMOVE_PASSWORD); |
+ [delegate_ model]->OnPasswordAction( |
+ *passwordForm_, ManagePasswordsBubbleModel::REMOVE_PASSWORD); |
} |
- (void)onUndoClicked:(id)sender { |
DCHECK_EQ(MANAGE_PASSWORD_ITEM_STATE_DELETED, state_); |
state_ = MANAGE_PASSWORD_ITEM_STATE_MANAGE; |
[self refresh]; |
- model_->OnPasswordAction(passwordForm_, |
- ManagePasswordsBubbleModel::ADD_PASSWORD); |
+ [delegate_ model]->OnPasswordAction(*passwordForm_, |
+ ManagePasswordsBubbleModel::ADD_PASSWORD); |
} |
- (void)refresh { |
[self updateContent]; |
- [self layoutContent]; |
+ [self layoutWithFirstColumn:[delegate_ firstColumnMaxWidth] |
+ secondColumn:[delegate_ secondColumnMaxWidth]]; |
} |
- (void)updateContent { |
switch (state_) { |
- default: |
- NOTREACHED(); |
case MANAGE_PASSWORD_ITEM_STATE_PENDING: |
contentView_.reset( |
- [[ManagePasswordItemPendingView alloc] initWithForm:passwordForm_]); |
+ [[PendingPasswordItemView alloc] initWithForm:*passwordForm_]); |
return; |
case MANAGE_PASSWORD_ITEM_STATE_MANAGE: |
- contentView_.reset([[ManagePasswordItemManageView alloc] |
- initWithForm:passwordForm_ |
+ contentView_.reset([[ManagePasswordItemView alloc] |
+ initWithForm:*passwordForm_ |
target:self |
action:@selector(onDeleteClicked:)]); |
return; |
case MANAGE_PASSWORD_ITEM_STATE_DELETED: |
- contentView_.reset([[ManagePasswordItemUndoView alloc] |
+ contentView_.reset([[UndoPasswordItemView alloc] |
initWithTarget:self |
action:@selector(onUndoClicked:)]); |
return; |
}; |
} |
-- (void)layoutContent { |
+- (void)loadView { |
+ self.view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease]; |
+} |
+ |
+#pragma mark PasswordItemTwoColumnView |
+ |
+- (void)layoutWithFirstColumn:(CGFloat)firstWidth |
+ secondColumn:(CGFloat)secondWidth { |
+ [contentView_ layoutWithFirstColumn:firstWidth secondColumn:secondWidth]; |
// Update the view size according to the content view size. |
const NSSize contentSize = [contentView_ frame].size; |
[self.view setFrameSize:contentSize]; |
@@ -371,9 +412,12 @@ base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
[self.view setSubviews:@[ contentView_ ]]; |
} |
-- (void)loadView { |
- self.view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease]; |
- [self layoutContent]; |
+- (CGFloat)firstColumnWidth { |
+ return [contentView_ firstColumnWidth]; |
+} |
+ |
+- (CGFloat)secondColumnWidth { |
+ return [contentView_ secondColumnWidth]; |
} |
@end |
@@ -388,43 +432,73 @@ base::string16 GetDisplayUsername(const autofill::PasswordForm& form) { |
return contentView_.get(); |
} |
-- (autofill::PasswordForm)passwordForm { |
- return passwordForm_; |
-} |
- |
@end |
-@implementation ManagePasswordItemClickableView |
+@implementation PasswordsListViewController |
+ |
+@synthesize firstColumnMaxWidth = firstColumnMaxWidth_; |
+@synthesize secondColumnMaxWidth = secondColumnMaxWidth_; |
-- (void)drawRect:(NSRect)dirtyRect { |
- [super drawRect:dirtyRect]; |
- if (hovering_) { |
- [HoverColor() setFill]; |
- NSRectFill(dirtyRect); |
+- (id)initWithModel:(ManagePasswordsBubbleModel*)model |
+ forms:(const PasswordFormsVector&)password_forms { |
+ if ((self = [super initWithNibName:nil bundle:nil])) { |
+ base::scoped_nsobject<NSMutableArray> items( |
+ [[NSMutableArray arrayWithCapacity:password_forms.size()] retain]); |
+ model_ = model; |
+ // Create the controllers. |
+ for (const autofill::PasswordForm* form : password_forms) { |
+ base::scoped_nsobject<ManagePasswordItemViewController> item( |
+ [[ManagePasswordItemViewController alloc] initWithDelegate:self |
+ passwordForm:form]); |
+ [items addObject:item.get()]; |
+ } |
+ itemViews_.reset(items.release()); |
} |
+ return self; |
} |
-- (void)mouseEntered:(NSEvent*)event { |
- hovering_ = YES; |
- [self setNeedsDisplay:YES]; |
+- (void)loadView { |
+ base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]); |
+ |
+ // Create the subviews. |
+ for (id object in itemViews_.get()) { |
+ ManagePasswordItemViewController* passwordController = |
+ base::mac::ObjCCast<ManagePasswordItemViewController>(object); |
+ NSView* itemView = [passwordController view]; |
+ [view addSubview:itemView]; |
+ firstColumnMaxWidth_ = |
+ std::max(firstColumnMaxWidth_, [passwordController firstColumnWidth]); |
+ secondColumnMaxWidth_ = |
+ std::max(secondColumnMaxWidth_, [passwordController secondColumnWidth]); |
+ } |
+ // Lay out the items. |
+ NSPoint curPos = {}; |
+ CGFloat maxX = 0; |
+ for (id object in [itemViews_ reverseObjectEnumerator]) { |
+ ManagePasswordItemViewController* passwordController = |
+ base::mac::ObjCCast<ManagePasswordItemViewController>(object); |
+ [passwordController layoutWithFirstColumn:firstColumnMaxWidth_ |
+ secondColumn:secondColumnMaxWidth_]; |
+ NSView* itemView = [passwordController view]; |
+ // The items stack up on each other. |
+ [itemView setFrameOrigin:curPos]; |
+ maxX = NSMaxX([itemView frame]); |
+ curPos.y = NSMaxY([itemView frame]); |
+ } |
+ [view setFrameSize:NSMakeSize(maxX, curPos.y)]; |
+ [self setView:view]; |
} |
-- (void)mouseExited:(NSEvent*)event { |
- hovering_ = NO; |
- [self setNeedsDisplay:YES]; |
+- (ManagePasswordsBubbleModel*)model { |
+ return model_; |
} |
-- (void)updateTrackingAreas { |
- [super updateTrackingAreas]; |
- if (trackingArea_.get()) |
- [self removeTrackingArea:trackingArea_.get()]; |
- NSTrackingAreaOptions options = |
- NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow; |
- trackingArea_.reset([[CrTrackingArea alloc] initWithRect:[self bounds] |
- options:options |
- owner:self |
- userInfo:nil]); |
- [self addTrackingArea:trackingArea_.get()]; |
+@end |
+ |
+@implementation PasswordsListViewController (Testing) |
+ |
+- (NSArray*)itemViews { |
+ return itemViews_.get(); |
} |
@end |