diff options
author | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-22 20:13:18 +0000 |
---|---|---|
committer | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-22 20:13:18 +0000 |
commit | db9fff737c9ea46f704017bb2bb135904a09e330 (patch) | |
tree | 3d148a18e2e4d8df394f43f71f46ab69e79d6d45 | |
parent | b42ebf48c6b35de78a2a6891f42ac056a4e87175 (diff) | |
download | chromium_src-db9fff737c9ea46f704017bb2bb135904a09e330.zip chromium_src-db9fff737c9ea46f704017bb2bb135904a09e330.tar.gz chromium_src-db9fff737c9ea46f704017bb2bb135904a09e330.tar.bz2 |
[Mac] Do not use the |title| field of the Page Info section, but the optional |headline|.
* As a consequence of this, the view into which we draw |-isFlipped==YES| so
layout now happens right-side up.
* Do not show the cert button unless it would be enabled.
BUG=59611
TEST=No more headings for "Identity" or "Connection".
Review URL: http://codereview.chromium.org/3771010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63551 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/cocoa/page_info_bubble_controller.mm | 139 | ||||
-rw-r--r-- | chrome/browser/cocoa/page_info_bubble_controller_unittest.mm | 35 |
2 files changed, 104 insertions, 70 deletions
diff --git a/chrome/browser/cocoa/page_info_bubble_controller.mm b/chrome/browser/cocoa/page_info_bubble_controller.mm index a2cc34f..b10c1cf 100644 --- a/chrome/browser/cocoa/page_info_bubble_controller.mm +++ b/chrome/browser/cocoa/page_info_bubble_controller.mm @@ -26,9 +26,9 @@ - (PageInfoModel*)model; - (NSButton*)certificateButtonWithFrame:(NSRect)frame; - (void)configureTextFieldAsLabel:(NSTextField*)textField; -- (CGFloat)addTitleViewForInfo:(const PageInfoModel::SectionInfo&)info - toSubviews:(NSMutableArray*)subviews - atPoint:(NSPoint)point; +- (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info + toSubviews:(NSMutableArray*)subviews + atPoint:(NSPoint)point; - (CGFloat)addDescriptionViewForInfo:(const PageInfoModel::SectionInfo&)info toSubviews:(NSMutableArray*)subviews atPoint:(NSPoint)point; @@ -45,6 +45,19 @@ parentWindow:(NSWindow*)parent; @end +// This simple NSView subclass is used as the single subview of the page info +// bubble's window's contentView. Drawing is flipped so that layout of the +// sections is easier. Apple recommends flipping the coordinate origin when +// doing a lot of text layout because it's more natural. +@interface PageInfoContentView : NSView { +} +@end +@implementation PageInfoContentView +- (BOOL)isFlipped { + return YES; +} +@end + namespace { // The width of the window, in view coordinates. The height will be determined @@ -57,8 +70,8 @@ const NSInteger kVerticalSpacing = 10; // Padding along on the X-axis between the window frame and content. const NSInteger kFramePadding = 20; -// Spacing between the title and description text views. -const NSInteger kTitleSpacing = 2; +// Spacing between the optional headline and description text views. +const NSInteger kHeadlineSpacing = 2; // Spacing between the image and the text. const NSInteger kImageSpacing = 10; @@ -173,28 +186,33 @@ void ShowPageInfoBubble(gfx::NativeWindow parent, // not using HTTPS. - (void)performLayout { // |offset| is the Y position that should be drawn at next. - CGFloat offset = kVerticalSpacing; + CGFloat offset = kFramePadding; // Keep the new subviews in an array that gets replaced at the end. NSMutableArray* subviews = [NSMutableArray array]; - // First item, drawn at the bottom of the window, is the help center link. - offset += [self addHelpButtonToSubviews:subviews atOffset:offset]; - offset += kVerticalSpacing; - offset += [self addSeparatorToSubviews:subviews atOffset:offset]; - - // Build the window from bottom-up because Cocoa's coordinate origin is the - // lower left. - for (int i = model_->GetSectionCount() - 1; i >= 0; --i) { + // The subviews will be attached to the PageInfoContentView, which has a + // flipped origin. This allows the code to build top-to-bottom. + const int sectionCount = model_->GetSectionCount(); + for (int i = 0; i < sectionCount; ++i) { PageInfoModel::SectionInfo info = model_->GetSectionInfo(i); // Only certain sections have images. This affects the X position. BOOL hasImage = model_->GetIconImage(info.icon_id) != nil; CGFloat xPosition = (hasImage ? kTextXPosition : kTextXPositionNoImage); - if (info.type == PageInfoModel::SECTION_INFO_IDENTITY) { - offset += [self addCertificateButtonToSubviews:subviews - atOffset:offset]; + // Insert the image subview for sections that are appropriate. + CGFloat imageBaseline = offset + kImageSize; + if (hasImage) { + [self addImageViewForInfo:info toSubviews:subviews atOffset:offset]; + } + + // Add the title. + if (!info.headline.empty()) { + offset += [self addHeadlineViewForInfo:info + toSubviews:subviews + atPoint:NSMakePoint(xPosition, offset)]; + offset += kHeadlineSpacing; } // Create the description of the state. @@ -202,31 +220,37 @@ void ShowPageInfoBubble(gfx::NativeWindow parent, toSubviews:subviews atPoint:NSMakePoint(xPosition, offset)]; - // Add the title. - offset += kTitleSpacing; - offset += [self addTitleViewForInfo:info - toSubviews:subviews - atPoint:NSMakePoint(xPosition, offset)]; - - // Insert the image subview for sections that are appropriate. - if (hasImage) { - [self addImageViewForInfo:info toSubviews:subviews atOffset:offset]; + if (info.type == PageInfoModel::SECTION_INFO_IDENTITY && certID_) { + offset += kVerticalSpacing; + offset += [self addCertificateButtonToSubviews:subviews atOffset:offset]; } + // If at this point the description and optional headline and button are + // not as tall as the image, adjust the offset by the difference. + CGFloat imageBaselineDelta = imageBaseline - offset; + if (imageBaselineDelta > 0) + offset += imageBaselineDelta; + // Add the separators. - if (i != 0) { - offset += kVerticalSpacing; - offset += [self addSeparatorToSubviews:subviews atOffset:offset]; - } + offset += kVerticalSpacing; + offset += [self addSeparatorToSubviews:subviews atOffset:offset]; } - // Replace the window's content. - [[[self window] contentView] setSubviews:subviews]; + // The last item at the bottom of the window is the help center link. + offset += [self addHelpButtonToSubviews:subviews atOffset:offset]; + offset += kVerticalSpacing; - offset += kFramePadding; + // Create the dummy view that uses flipped coordinates. + NSRect contentFrame = NSMakeRect(0, 0, kWindowWidth, offset); + scoped_nsobject<PageInfoContentView> contentView( + [[PageInfoContentView alloc] initWithFrame:contentFrame]); + [contentView setSubviews:subviews]; - NSRect windowFrame = NSMakeRect(0, 0, kWindowWidth, 0); - windowFrame.size.height += offset; + // Replace the window's content. + [[[self window] contentView] setSubviews: + [NSArray arrayWithObject:contentView]]; + + NSRect windowFrame = NSMakeRect(0, 0, kWindowWidth, offset); windowFrame.size = [[[self window] contentView] convertSize:windowFrame.size toView:nil]; // Adjust the origin by the difference in height. @@ -273,21 +297,21 @@ void ShowPageInfoBubble(gfx::NativeWindow parent, // Adds the title text field at the given x,y position, and returns the y // position for the next element. -- (CGFloat)addTitleViewForInfo:(const PageInfoModel::SectionInfo&)info - toSubviews:(NSMutableArray*)subviews - atPoint:(NSPoint)point { +- (CGFloat)addHeadlineViewForInfo:(const PageInfoModel::SectionInfo&)info + toSubviews:(NSMutableArray*)subviews + atPoint:(NSPoint)point { NSRect frame = NSMakeRect(point.x, point.y, kTextWidth, kImageSpacing); - scoped_nsobject<NSTextField> titleField( + scoped_nsobject<NSTextField> textField( [[NSTextField alloc] initWithFrame:frame]); - [self configureTextFieldAsLabel:titleField.get()]; - [titleField setStringValue:base::SysUTF16ToNSString(info.title)]; + [self configureTextFieldAsLabel:textField.get()]; + [textField setStringValue:base::SysUTF16ToNSString(info.headline)]; NSFont* font = [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]]; - [titleField setFont:font]; + [textField setFont:font]; frame.size.height += [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField: - titleField]; - [titleField setFrame:frame]; - [subviews addObject:titleField.get()]; + textField]; + [textField setFrame:frame]; + [subviews addObject:textField.get()]; return NSHeight(frame); } @@ -315,6 +339,9 @@ void ShowPageInfoBubble(gfx::NativeWindow parent, // Returns the y position for the next element. - (CGFloat)addCertificateButtonToSubviews:(NSMutableArray*)subviews atOffset:(CGFloat)offset { + // The certificate button should only be added if there is SSL information. + DCHECK(certID_); + // Create the certificate button. The frame will be fixed up by GTM, so // use arbitrary values. NSRect frame = NSMakeRect(kTextXPosition, offset, 100, 14); @@ -323,19 +350,17 @@ void ShowPageInfoBubble(gfx::NativeWindow parent, [GTMUILocalizerAndLayoutTweaker sizeToFitView:certButton]; // By default, assume that we don't have certificate information to show. - [certButton setEnabled:NO]; - if (certID_) { - scoped_refptr<net::X509Certificate> cert; - CertStore::GetSharedInstance()->RetrieveCert(certID_, &cert); - - // Don't bother showing certificates if there isn't one. Gears runs - // with no OS root certificate. - if (cert.get() && cert->os_cert_handle()) { - [certButton setEnabled:YES]; - } + scoped_refptr<net::X509Certificate> cert; + CertStore::GetSharedInstance()->RetrieveCert(certID_, &cert); + + // Don't bother showing certificates if there isn't one. Gears runs + // with no OS root certificate. + if (!cert.get() || !cert->os_cert_handle()) { + // This should only ever happen in unit tests. + [certButton setEnabled:NO]; } - return NSHeight(frame) + kVerticalSpacing; + return NSHeight([certButton frame]); } // Adds the state image at a pre-determined x position and the given y. This @@ -344,7 +369,7 @@ void ShowPageInfoBubble(gfx::NativeWindow parent, - (void)addImageViewForInfo:(const PageInfoModel::SectionInfo&)info toSubviews:(NSMutableArray*)subviews atOffset:(CGFloat)offset { - NSRect frame = NSMakeRect(kFramePadding, offset - kImageSize, kImageSize, + NSRect frame = NSMakeRect(kFramePadding, offset, kImageSize, kImageSize); scoped_nsobject<NSImageView> imageView( [[NSImageView alloc] initWithFrame:frame]); diff --git a/chrome/browser/cocoa/page_info_bubble_controller_unittest.mm b/chrome/browser/cocoa/page_info_bubble_controller_unittest.mm index eb7c177..da8a9db 100644 --- a/chrome/browser/cocoa/page_info_bubble_controller_unittest.mm +++ b/chrome/browser/cocoa/page_info_bubble_controller_unittest.mm @@ -22,11 +22,11 @@ class FakeModel : public PageInfoModel { FakeModel() : PageInfoModel() {} void AddSection(SectionStateIcon icon_id, - const string16& title, + const string16& headline, const string16& description, SectionInfoType type) { sections_.push_back(SectionInfo( - icon_id, title, string16(), description, type)); + icon_id, string16(), headline, description, type)); } }; @@ -67,7 +67,13 @@ class PageInfoBubbleControllerTest : public CocoaTest { int link_count = 1; ++spacer_count; - for (NSView* view in [[window_ contentView] subviews]) { + // The window's only immediate child is an invisible view that has a flipped + // coordinate origin. It is into this that all views get placed. + NSArray* windowSubviews = [[window_ contentView] subviews]; + EXPECT_EQ(1U, [windowSubviews count]); + NSArray* subviews = [[windowSubviews lastObject] subviews]; + + for (NSView* view in subviews) { if ([view isKindOfClass:[NSTextField class]]) { --text_count; } else if ([view isKindOfClass:[NSImageView class]]) { @@ -113,28 +119,28 @@ class PageInfoBubbleControllerTest : public CocoaTest { TEST_F(PageInfoBubbleControllerTest, NoHistoryNoSecurity) { model_->AddSection(PageInfoModel::ICON_STATE_ERROR, - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_IDENTITY_TITLE), + string16(), l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY), PageInfoModel::SECTION_INFO_IDENTITY); model_->AddSection(PageInfoModel::ICON_STATE_ERROR, - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_CONNECTION_TITLE), + string16(), l10n_util::GetStringFUTF16( IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, ASCIIToUTF16("google.com")), PageInfoModel::SECTION_INFO_CONNECTION); CreateBubble(); - CheckWindow(/*text=*/4, /*image=*/2, /*spacer=*/1, /*button=*/1); + CheckWindow(/*text=*/2, /*image=*/2, /*spacer=*/1, /*button=*/0); } TEST_F(PageInfoBubbleControllerTest, HistoryNoSecurity) { model_->AddSection(PageInfoModel::ICON_STATE_ERROR, - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_IDENTITY_TITLE), + string16(), l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY), PageInfoModel::SECTION_INFO_IDENTITY); model_->AddSection(PageInfoModel::ICON_STATE_ERROR, - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_CONNECTION_TITLE), + string16(), l10n_util::GetStringFUTF16( IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, ASCIIToUTF16("google.com")), @@ -153,13 +159,13 @@ TEST_F(PageInfoBubbleControllerTest, HistoryNoSecurity) { [controller_ performLayout]; - CheckWindow(/*text=*/6, /*image=*/3, /*spacer=*/2, /*button=*/1); + CheckWindow(/*text=*/4, /*image=*/3, /*spacer=*/2, /*button=*/0); } TEST_F(PageInfoBubbleControllerTest, NoHistoryMixedSecurity) { model_->AddSection(PageInfoModel::ICON_STATE_OK, - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_IDENTITY_TITLE), + string16(), l10n_util::GetStringFUTF16( IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY, ASCIIToUTF16("Goat Security Systems")), @@ -177,17 +183,20 @@ TEST_F(PageInfoBubbleControllerTest, NoHistoryMixedSecurity) { IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNING)); model_->AddSection(PageInfoModel::ICON_STATE_OK, - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_CONNECTION_TITLE), + string16(), description, PageInfoModel::SECTION_INFO_CONNECTION); + CreateBubble(); + [controller_ setCertID:1]; + [controller_ performLayout]; - NSArray* subviews = [[window_ contentView] subviews]; - CheckWindow(/*text=*/4, /*image=*/2, /*spacer=*/1, /*button=*/1); + CheckWindow(/*text=*/2, /*image=*/2, /*spacer=*/1, /*button=*/1); // Look for the over-sized box. NSString* targetDesc = base::SysUTF16ToNSString(description); + NSArray* subviews = [[window_ contentView] subviews]; for (NSView* subview in subviews) { if ([subview isKindOfClass:[NSTextField class]]) { NSTextField* desc = static_cast<NSTextField*>(subview); |