diff options
author | andresantoso <andresantoso@chromium.org> | 2015-06-01 18:01:00 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-02 01:01:45 +0000 |
commit | e59a7b6cbad6b0aa04e01d9f3c0021ee1ee03e8a (patch) | |
tree | 677e9a4109f2813695274a5dd316e8e93c9d31c7 | |
parent | 298d6b7b03f7383d51e4792be8b1d2d162281e6a (diff) | |
download | chromium_src-e59a7b6cbad6b0aa04e01d9f3c0021ee1ee03e8a.zip chromium_src-e59a7b6cbad6b0aa04e01d9f3c0021ee1ee03e8a.tar.gz chromium_src-e59a7b6cbad6b0aa04e01d9f3c0021ee1ee03e8a.tar.bz2 |
Mac: Update sad tab layout to new design
Update sad tab layout to new design and match the other platforms.
Add a button for reloading the page.
Fixed BlueLabelButton to enable LCD font smoothing when layer backed.
BUG=490139
Review URL: https://codereview.chromium.org/1145063005
Cr-Commit-Position: refs/heads/master@{#332284}
6 files changed, 178 insertions, 149 deletions
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index d2c81e5..06b489a 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm @@ -63,7 +63,6 @@ #import "chrome/browser/ui/cocoa/profiles/avatar_icon_controller.h" #import "chrome/browser/ui/cocoa/status_bubble_mac.h" #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h" -#import "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h" #import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h" #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" @@ -1931,19 +1930,15 @@ using content::WebContents; [self layoutSubviews]; } -// Handle the openLearnMoreAboutCrashLink: action from SadTabController when +// Handle the openLearnMoreAboutCrashLink: action from SadTabView when // "Learn more" link in "Aw snap" page (i.e. crash page or sad tab) is // clicked. Decoupling the action from its target makes unit testing possible. - (void)openLearnMoreAboutCrashLink:(id)sender { - if (SadTabController* sadTab = - base::mac::ObjCCast<SadTabController>(sender)) { - WebContents* webContents = [sadTab webContents]; - if (webContents) { - OpenURLParams params( - GURL(chrome::kCrashReasonURL), Referrer(), CURRENT_TAB, - ui::PAGE_TRANSITION_LINK, false); - webContents->OpenURL(params); - } + if (WebContents* webContents = + browser_->tab_strip_model()->GetActiveWebContents()) { + OpenURLParams params(GURL(chrome::kCrashReasonURL), Referrer(), CURRENT_TAB, + ui::PAGE_TRANSITION_LINK, false); + webContents->OpenURL(params); } } diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm index a2073e1..6e49e8e 100644 --- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm +++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm @@ -36,6 +36,7 @@ void SadTabCocoa::Close() { - (id)initWithWebContents:(content::WebContents*)webContents { if ((self = [super init])) { + DCHECK(webContents); webContents_ = webContents; if (webContents_) { // NULL in unit_tests. @@ -52,8 +53,8 @@ void SadTabCocoa::Close() { - (void)loadView { base::scoped_nsobject<SadTabView> sadView([[SadTabView alloc] init]); - if (!webContents_) - [sadView removeHelpText]; + [[sadView reloadButton] setTarget:self]; + [[sadView reloadButton] setAction:@selector(reloadPage:)]; [self setView:sadView]; } @@ -61,4 +62,8 @@ void SadTabCocoa::Close() { return webContents_; } +- (IBAction)reloadPage:(id)sender { + webContents_->GetController().Reload(true); +} + @end diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm index 4ef94a1..08168aa 100644 --- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_controller_unittest.mm @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/debug/debugger.h" +#import "base/mac/foundation_util.h" #include "base/mac/scoped_nsobject.h" #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" #import "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h" @@ -18,7 +19,12 @@ @implementation SadTabView (ExposedForTesting) - (HyperlinkTextView*)helpTextView { - return help_.get(); + NSView* containerView = [[self subviews] lastObject]; + for (NSView* view in [containerView subviews]) { + if (auto textView = base::mac::ObjCCast<HyperlinkTextView>(view)) + return textView; + } + return nil; } @end @@ -74,21 +80,6 @@ class SadTabControllerTest : public ChromeRenderViewHostTestHarness { // static bool SadTabControllerTest::link_clicked_; -TEST_F(SadTabControllerTest, WithTabContents) { - base::scoped_nsobject<SadTabController> controller(CreateController()); - EXPECT_TRUE(controller); - HyperlinkTextView* help = GetHelpTextView(controller); - EXPECT_TRUE(help); -} - -TEST_F(SadTabControllerTest, WithoutTabContents) { - DeleteContents(); - base::scoped_nsobject<SadTabController> controller(CreateController()); - EXPECT_TRUE(controller); - HyperlinkTextView* help = GetHelpTextView(controller); - EXPECT_FALSE(help); -} - TEST_F(SadTabControllerTest, ClickOnLink) { base::scoped_nsobject<SadTabController> controller(CreateController()); HyperlinkTextView* help = GetHelpTextView(controller); diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h index 306ad4c..e5f420a 100644 --- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h +++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h @@ -9,26 +9,19 @@ #import <Cocoa/Cocoa.h> -@class HyperlinkTextView; +namespace content { +class WebContents; +} + +@class SadTabContainerView; // A view that displays the "sad tab" (aka crash page). -@interface SadTabView : NSView<NSTextViewDelegate> { +@interface SadTabView : NSView { @private - base::scoped_nsobject<NSImageView> image_; - base::scoped_nsobject<NSTextField> title_; - base::scoped_nsobject<NSTextField> message_; - base::scoped_nsobject<HyperlinkTextView> help_; - - NSSize messageSize_; + base::scoped_nsobject<SadTabContainerView> container_; } -// Designated initializer is -initWithFrame: . - -// Called by SadTabController to remove the help text and link. -- (void)removeHelpText; - -// Sets |help_| based on |helpPlaceholder_|, sets |helpPlaceholder_| to nil. -- (void)initializeHelpText; +@property(readonly,nonatomic) NSButton* reloadButton; @end diff --git a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.mm b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.mm index 3a32f1f..c831e68 100644 --- a/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.mm +++ b/chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.mm @@ -10,6 +10,7 @@ #include "chrome/grit/generated_resources.h" #include "grit/theme_resources.h" #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" +#import "ui/base/cocoa/controls/blue_label_button.h" #import "ui/base/cocoa/controls/hyperlink_text_view.h" #import "ui/base/cocoa/nscolor_additions.h" #include "ui/base/l10n/l10n_util.h" @@ -17,36 +18,43 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/image/image.h" -// Offset above vertical middle of page where contents of page start. -static const CGFloat kSadTabOffset = -64; +// Maximum width used by page contents. +static const CGFloat kMaxContainerWidth = 600; // Padding between icon and title. -static const CGFloat kIconTitleSpacing = 20; +static const CGFloat kIconTitleSpacing = 40; // Padding between title and message. -static const CGFloat kTitleMessageSpacing = 15; +static const CGFloat kTitleMessageSpacing = 18; // Padding between message and link. -static const CGFloat kMessageLinkSpacing = 15; -// Paddings on left and right of page. -static const CGFloat kTabHorzMargin = 13; -// The width and height of the icon image view. -static const CGFloat kIconViewSize = 66; +static const CGFloat kMessageLinkSpacing = 21; +// Padding between link and button. +static const CGFloat kLinkButtonSpacing = 55; +// Minimum margins on all sides. +static const CGFloat kTabMargin = 13; +// Maximum margin on top. +static const CGFloat kMaxTopMargin = 100; @interface SadTabTextView : NSTextField -- (id)initWithView:(SadTabView*)view withText:(int)textIds; +- (id)initWithStringResourceID:(int)stringResourceID; @end @implementation SadTabTextView -- (id)initWithView:(SadTabView*)view withText:(int)textIds { +- (id)initWithStringResourceID:(int)stringResourceID { if (self = [super init]) { - [self setAlignment:NSCenterTextAlignment]; - [self setStringValue:l10n_util::GetNSString(textIds)]; + base::scoped_nsobject<NSMutableParagraphStyle> style( + [[NSMutableParagraphStyle alloc] init]); + [style setLineSpacing:6]; + base::scoped_nsobject<NSAttributedString> title([[NSAttributedString alloc] + initWithString:l10n_util::GetNSString(stringResourceID) + attributes:@{ NSParagraphStyleAttributeName : style }]); + [self setAttributedStringValue:title]; + + [self setAlignment:NSLeftTextAlignment]; [self setEditable:NO]; [self setBezeled:NO]; - [self setAutoresizingMask: - NSViewMinXMargin|NSViewWidthSizable|NSViewMaxXMargin|NSViewMinYMargin]; - [view addSubview:self]; + [self setAutoresizingMask:NSViewWidthSizable|NSViewMaxYMargin]; } return self; } @@ -57,112 +65,97 @@ static const CGFloat kIconViewSize = 66; @end -@implementation SadTabView +@interface SadTabContainerView : NSView<NSTextViewDelegate> { + @private + base::scoped_nsobject<NSImageView> image_; + base::scoped_nsobject<NSTextField> title_; + base::scoped_nsobject<NSTextField> message_; + base::scoped_nsobject<HyperlinkTextView> help_; + base::scoped_nsobject<NSButton> button_; +} -- (instancetype)initWithFrame:(NSRect)frame { - if ((self = [super initWithFrame:frame])) { +- (instancetype)initWithBackgroundColor:(NSColor*)backgroundColor; + +@property(readonly,nonatomic) NSButton* reloadButton; + +// The height to fit the content elements within the current width. +@property(readonly,nonatomic) CGFloat contentHeight; + +@end + +@implementation SadTabContainerView + +- (instancetype)initWithBackgroundColor:(NSColor*)backgroundColor { + if ((self = [super initWithFrame:NSZeroRect])) { // Load resource for image and set it. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - image_.reset([[NSImageView alloc] - initWithFrame:NSMakeRect(0, 0, kIconViewSize, kIconViewSize)]); - [image_ setImage:rb.GetNativeImageNamed(IDR_SAD_TAB).ToNSImage()]; + NSImage* iconImage = rb.GetNativeImageNamed(IDR_SAD_TAB).ToNSImage(); + NSRect imageFrame = NSZeroRect; + imageFrame.size = [iconImage size]; + image_.reset([[NSImageView alloc] initWithFrame:imageFrame]); + [image_ setImage:iconImage]; + [image_ setAutoresizingMask:NSViewMaxXMargin|NSViewMaxYMargin]; [self addSubview:image_]; - // Initialize background color. - NSColor* backgroundColor = [NSColor colorWithCalibratedWhite:247.0f/255.0f - alpha:1.0]; - [self setWantsLayer:YES]; - [[self layer] setBackgroundColor:[backgroundColor cr_CGColor]]; - // Set up the title. - title_.reset([[SadTabTextView alloc] - initWithView:self withText:IDS_SAD_TAB_TITLE]); + title_.reset( + [[SadTabTextView alloc] initWithStringResourceID:IDS_SAD_TAB_TITLE]); [title_ setFont:[NSFont systemFontOfSize:24]]; [title_ setBackgroundColor:backgroundColor]; - [title_ setTextColor:[NSColor colorWithCalibratedWhite:51.0f/255.0f + [title_ setTextColor:[NSColor colorWithCalibratedWhite:38.0f/255.0f alpha:1.0]]; + [title_ sizeToFit]; + [title_ setFrameOrigin: + NSMakePoint(0, NSMaxY(imageFrame) + kIconTitleSpacing)]; + [self addSubview:title_]; // Set up the message. - message_.reset([[SadTabTextView alloc] - initWithView:self withText:IDS_SAD_TAB_MESSAGE]); - [message_ setFont:[NSFont systemFontOfSize:15]]; + message_.reset( + [[SadTabTextView alloc] initWithStringResourceID:IDS_SAD_TAB_MESSAGE]); + [message_ setFont:[NSFont systemFontOfSize:14]]; [message_ setBackgroundColor:backgroundColor]; - [message_ setTextColor:[NSColor colorWithCalibratedWhite:100.0f/255.0f + [message_ setTextColor:[NSColor colorWithCalibratedWhite:81.0f/255.0f alpha:1.0]]; + [message_ setFrameOrigin: + NSMakePoint(0, NSMaxY([title_ frame]) + kTitleMessageSpacing)]; + [self addSubview:message_]; [self initializeHelpText]; + + button_.reset([[BlueLabelButton alloc] init]); + [button_ setTitle:l10n_util::GetNSString(IDS_SAD_TAB_RELOAD_LABEL)]; + [button_ sizeToFit]; + [button_ setTarget:self]; + [button_ setAction:@selector(reloadPage:)]; + [self addSubview:button_]; } return self; } -- (void)resizeSubviewsWithOldSize:(NSSize)oldSize { - NSRect newBounds = [self bounds]; - CGFloat maxWidth = NSWidth(newBounds) - (kTabHorzMargin * 2); - BOOL callSizeToFit = (messageSize_.width == 0); - - // Set new frame origin for image. - NSRect iconFrame = [image_ frame]; - CGFloat iconX = floorf((maxWidth - NSWidth(iconFrame)) / 2); - CGFloat iconY = - MIN(floorf((NSHeight(newBounds) - NSHeight(iconFrame)) / 2) - - kSadTabOffset, - NSHeight(newBounds) - NSHeight(iconFrame)); - iconX = floorf(iconX); - iconY = floorf(iconY); - [image_ setFrameOrigin:NSMakePoint(iconX, iconY)]; - - // Set new frame origin for title. - if (callSizeToFit) - [title_ sizeToFit]; - NSRect titleFrame = [title_ frame]; - CGFloat titleX = floorf((maxWidth - NSWidth(titleFrame)) / 2); - CGFloat titleY = iconY - kIconTitleSpacing - NSHeight(titleFrame); - [title_ setFrameOrigin:NSMakePoint(titleX, titleY)]; - - // Set new frame for message, wrapping or unwrapping the text if necessary. - if (callSizeToFit) { - [message_ sizeToFit]; - messageSize_ = [message_ frame].size; - } - NSRect messageFrame = [message_ frame]; - if (messageSize_.width > maxWidth) { // Need to wrap message. - [message_ setFrameSize:NSMakeSize(maxWidth, messageSize_.height)]; - CGFloat heightChange = - [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_]; - messageFrame.size.width = maxWidth; - messageFrame.size.height = messageSize_.height + heightChange; - messageFrame.origin.x = kTabHorzMargin; - } else { - if (!callSizeToFit) { - [message_ sizeToFit]; - messageFrame = [message_ frame]; - } - messageFrame.origin.x = floorf((maxWidth - NSWidth(messageFrame)) / 2); - } - messageFrame.origin.y = - titleY - kTitleMessageSpacing - NSHeight(messageFrame); - [message_ setFrame:messageFrame]; - - // Set new frame for help text and link. - if (help_) { - if (callSizeToFit) - [help_ sizeToFit]; - CGFloat helpHeight = [help_ frame].size.height; - [help_ setFrameSize:NSMakeSize(maxWidth, helpHeight)]; - // Set new frame origin for link. - NSRect helpFrame = [help_ frame]; - CGFloat helpX = floorf((maxWidth - NSWidth(helpFrame)) / 2); - CGFloat helpY = - NSMinY(messageFrame) - kMessageLinkSpacing - NSHeight(helpFrame); - [help_ setFrameOrigin:NSMakePoint(helpX, helpY)]; - } +- (BOOL)isFlipped { + return YES; } -- (void)removeHelpText { - if (help_) { - [help_ removeFromSuperview]; - help_.reset(nil); - } +- (NSButton*)reloadButton { + return button_; +} + +- (CGFloat)contentHeight { + return NSMaxY([button_ frame]); +} + +- (void)resizeSubviewsWithOldSize:(NSSize)oldSize { + [super resizeSubviewsWithOldSize:oldSize]; + + // |message_| can wrap to variable number of lines. + [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_]; + + [help_ setFrameOrigin: + NSMakePoint(0, NSMaxY([message_ frame]) + kMessageLinkSpacing)]; + + [button_ setFrameOrigin: + NSMakePoint(NSMaxX([self bounds]) - NSWidth([button_ frame]), + NSMaxY([help_ frame]) + kLinkButtonSpacing)]; } - (void)initializeHelpText { @@ -171,10 +164,10 @@ static const CGFloat kIconViewSize = 66; NSFont* helpFont = [message_ font]; NSRect helpFrame = NSMakeRect(0, 0, 1, [helpFont pointSize] + 4); help_.reset([[HyperlinkTextView alloc] initWithFrame:helpFrame]); - [help_ setAutoresizingMask: - NSViewMinXMargin|NSViewWidthSizable|NSViewMaxXMargin|NSViewMinYMargin]; + [help_ setAutoresizingMask:NSViewWidthSizable|NSViewMaxYMargin]; [help_ setDrawsBackground:YES]; [help_ setBackgroundColor:[message_ backgroundColor]]; + [[help_ textContainer] setLineFragmentPadding:2]; // To align with message_. [self addSubview:help_]; [help_ setDelegate:self]; @@ -190,7 +183,8 @@ static const CGFloat kIconViewSize = 66; [help_ addLinkRange:NSMakeRange(linkOffset, helpLink.length()) withName:@"" linkColor:[message_ textColor]]; - [help_ setAlignment:NSCenterTextAlignment]; + [help_ setAlignment:NSLeftTextAlignment]; + [help_ sizeToFit]; } // Called when someone clicks on the embedded link. @@ -202,3 +196,48 @@ static const CGFloat kIconViewSize = 66; } @end + +@implementation SadTabView + +- (instancetype)initWithFrame:(NSRect)frame { + if ((self = [super initWithFrame:frame])) { + [self setWantsLayer:YES]; + + NSColor* backgroundColor = [NSColor colorWithCalibratedWhite:245.0f/255.0f + alpha:1.0]; + [[self layer] setBackgroundColor:[backgroundColor cr_CGColor]]; + + container_.reset( + [[SadTabContainerView alloc] initWithBackgroundColor:backgroundColor]); + [self addSubview:container_]; + } + return self; +} + +- (BOOL)isFlipped { + return YES; +} + +- (void)resizeSubviewsWithOldSize:(NSSize)oldSize { + NSRect bounds = [self bounds]; + + // Set the container size first because its contentHeight will depend on its + // width. + NSSize frameSize = NSMakeSize( + std::min(NSWidth(bounds) - 2 * kTabMargin, kMaxContainerWidth), + NSHeight(bounds)); + [container_ setFrameSize:frameSize]; + + // Center horizontally. + // Top margin is at least kTabMargin and at most kMaxTopMargin. + [container_ setFrameOrigin:NSMakePoint( + floor((NSWidth(bounds) - frameSize.width) / 2), + std::min(kMaxTopMargin, std::max(kTabMargin, + NSHeight(bounds) - [container_ contentHeight] - kTabMargin)))]; +} + +- (NSButton*)reloadButton { + return [container_ reloadButton]; +} + +@end diff --git a/ui/base/cocoa/controls/blue_label_button.mm b/ui/base/cocoa/controls/blue_label_button.mm index fad0a01..d602146 100644 --- a/ui/base/cocoa/controls/blue_label_button.mm +++ b/ui/base/cocoa/controls/blue_label_button.mm @@ -93,9 +93,15 @@ const SkColor kPressOuterRingColor = SkColorSetRGB(0x23, 0x52, 0xa2); // Fuzz factor to adjust for the drop shadow. Based on visual inspection. frame.origin.y -= 1; + // Ensure LCD font smoothing is enabled when layer backed. + // This is safe to do because we know we are drawing on an opaque background. + gfx::ScopedNSGraphicsContextSaveGState scopedGState; + NSGraphicsContext* context = [NSGraphicsContext currentContext]; + CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]); + CGContextSetShouldSmoothFonts(cgContext, true); + NSAttributedString* attributedTitle = [[self class] generateAttributedString:[self title]]; - gfx::ScopedNSGraphicsContextSaveGState context; [attributedTitle drawInRect:frame]; return frame; } |