1// Copyright (c) 2012 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. 4 5#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h" 6 7#include "base/logging.h" 8#include "base/strings/sys_string_conversions.h" 9#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h" 10#include "chrome/common/url_constants.h" 11#include "chrome/grit/generated_resources.h" 12#include "grit/theme_resources.h" 13#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" 14#import "ui/base/cocoa/controls/hyperlink_text_view.h" 15#include "ui/base/l10n/l10n_util.h" 16#include "ui/base/l10n/l10n_util_mac.h" 17#include "ui/base/resource/resource_bundle.h" 18#include "ui/gfx/image/image.h" 19 20// Offset above vertical middle of page where contents of page start. 21static const CGFloat kSadTabOffset = -64; 22// Padding between icon and title. 23static const CGFloat kIconTitleSpacing = 20; 24// Padding between title and message. 25static const CGFloat kTitleMessageSpacing = 15; 26// Padding between message and link. 27static const CGFloat kMessageLinkSpacing = 15; 28// Paddings on left and right of page. 29static const CGFloat kTabHorzMargin = 13; 30 31@interface SadTabTextView : NSTextField 32 33- (id)initWithView:(SadTabView*)view withText:(int)textIds; 34 35@end 36 37@implementation SadTabTextView 38 39- (id)initWithView:(SadTabView*)view withText:(int)textIds { 40 if (self = [super init]) { 41 [self setTextColor:[NSColor whiteColor]]; 42 [self setAlignment:NSCenterTextAlignment]; 43 [self setStringValue:l10n_util::GetNSString(textIds)]; 44 [self setEditable:NO]; 45 [self setBezeled:NO]; 46 [self setAutoresizingMask: 47 NSViewMinXMargin|NSViewWidthSizable|NSViewMaxXMargin|NSViewMinYMargin]; 48 [view addSubview:self]; 49 } 50 return self; 51} 52 53- (BOOL)isOpaque { 54 return YES; 55} 56 57@end 58 59@implementation SadTabView 60 61- (void)awakeFromNib { 62 // Load resource for image and set it. 63 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 64 NSImage* image = rb.GetNativeImageNamed(IDR_SAD_TAB).ToNSImage(); 65 [image_ setImage:image]; 66 67 68 // Initialize background color. 69 NSColor* backgroundColor = [[NSColor colorWithCalibratedRed:(35.0f/255.0f) 70 green:(48.0f/255.0f) 71 blue:(64.0f/255.0f) 72 alpha:1.0] retain]; 73 backgroundColor_.reset(backgroundColor); 74 75 // Set up the title. 76 title_.reset([[SadTabTextView alloc] 77 initWithView:self withText:IDS_SAD_TAB_TITLE]); 78 [title_ setFont:[NSFont boldSystemFontOfSize:[NSFont systemFontSize]]]; 79 [title_ setBackgroundColor:backgroundColor]; 80 81 // Set up the message. 82 message_.reset([[SadTabTextView alloc] 83 initWithView:self withText:IDS_SAD_TAB_MESSAGE]); 84 [message_ setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; 85 [message_ setBackgroundColor:backgroundColor]; 86 87 DCHECK(controller_); 88 [self initializeHelpText]; 89} 90 91- (void)drawRect:(NSRect)dirtyRect { 92 // Paint background. 93 [backgroundColor_ set]; 94 NSRectFill(dirtyRect); 95} 96 97- (void)resizeSubviewsWithOldSize:(NSSize)oldSize { 98 NSRect newBounds = [self bounds]; 99 CGFloat maxWidth = NSWidth(newBounds) - (kTabHorzMargin * 2); 100 BOOL callSizeToFit = (messageSize_.width == 0); 101 102 // Set new frame origin for image. 103 NSRect iconFrame = [image_ frame]; 104 CGFloat iconX = floorf((maxWidth - NSWidth(iconFrame)) / 2); 105 CGFloat iconY = 106 MIN(floorf((NSHeight(newBounds) - NSHeight(iconFrame)) / 2) - 107 kSadTabOffset, 108 NSHeight(newBounds) - NSHeight(iconFrame)); 109 iconX = floorf(iconX); 110 iconY = floorf(iconY); 111 [image_ setFrameOrigin:NSMakePoint(iconX, iconY)]; 112 113 // Set new frame origin for title. 114 if (callSizeToFit) 115 [title_ sizeToFit]; 116 NSRect titleFrame = [title_ frame]; 117 CGFloat titleX = floorf((maxWidth - NSWidth(titleFrame)) / 2); 118 CGFloat titleY = iconY - kIconTitleSpacing - NSHeight(titleFrame); 119 [title_ setFrameOrigin:NSMakePoint(titleX, titleY)]; 120 121 // Set new frame for message, wrapping or unwrapping the text if necessary. 122 if (callSizeToFit) { 123 [message_ sizeToFit]; 124 messageSize_ = [message_ frame].size; 125 } 126 NSRect messageFrame = [message_ frame]; 127 if (messageSize_.width > maxWidth) { // Need to wrap message. 128 [message_ setFrameSize:NSMakeSize(maxWidth, messageSize_.height)]; 129 CGFloat heightChange = 130 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_]; 131 messageFrame.size.width = maxWidth; 132 messageFrame.size.height = messageSize_.height + heightChange; 133 messageFrame.origin.x = kTabHorzMargin; 134 } else { 135 if (!callSizeToFit) { 136 [message_ sizeToFit]; 137 messageFrame = [message_ frame]; 138 } 139 messageFrame.origin.x = floorf((maxWidth - NSWidth(messageFrame)) / 2); 140 } 141 messageFrame.origin.y = 142 titleY - kTitleMessageSpacing - NSHeight(messageFrame); 143 [message_ setFrame:messageFrame]; 144 145 // Set new frame for help text and link. 146 if (help_) { 147 if (callSizeToFit) 148 [help_ sizeToFit]; 149 CGFloat helpHeight = [help_ frame].size.height; 150 [help_ setFrameSize:NSMakeSize(maxWidth, helpHeight)]; 151 // Set new frame origin for link. 152 NSRect helpFrame = [help_ frame]; 153 CGFloat helpX = floorf((maxWidth - NSWidth(helpFrame)) / 2); 154 CGFloat helpY = 155 NSMinY(messageFrame) - kMessageLinkSpacing - NSHeight(helpFrame); 156 [help_ setFrameOrigin:NSMakePoint(helpX, helpY)]; 157 } 158} 159 160- (void)removeHelpText { 161 if (help_) { 162 [help_ removeFromSuperview]; 163 help_.reset(nil); 164 } 165} 166 167- (void)initializeHelpText { 168 // Programmatically create the help link. Note that the frame's initial 169 // height must be set for the programmatic resizing to work. 170 help_.reset( 171 [[HyperlinkTextView alloc] initWithFrame:NSMakeRect(0, 0, 1, 17)]); 172 [help_ setAutoresizingMask: 173 NSViewMinXMargin|NSViewWidthSizable|NSViewMaxXMargin|NSViewMinYMargin]; 174 [self addSubview:help_]; 175 [help_ setDelegate:self]; 176 177 // Get the help text and link. 178 size_t linkOffset = 0; 179 NSString* helpMessage(base::SysUTF16ToNSString(l10n_util::GetStringFUTF16( 180 IDS_SAD_TAB_HELP_MESSAGE, base::string16(), &linkOffset))); 181 NSString* helpLink = l10n_util::GetNSString(IDS_SAD_TAB_HELP_LINK); 182 NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; 183 [help_ setMessageAndLink:helpMessage 184 withLink:helpLink 185 atOffset:linkOffset 186 font:font 187 messageColor:[NSColor whiteColor] 188 linkColor:[NSColor whiteColor]]; 189 [help_ setAlignment:NSCenterTextAlignment]; 190} 191 192// Called when someone clicks on the embedded link. 193- (BOOL)textView:(NSTextView*)textView 194 clickedOnLink:(id)link 195 atIndex:(NSUInteger)charIndex { 196 if (controller_) 197 [controller_ openLearnMoreAboutCrashLink:nil]; 198 return YES; 199} 200 201@end 202