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.
5 #include "chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h"
7 #include "base/logging.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "chrome/common/url_constants.h"
10 #include "chrome/grit/generated_resources.h"
11 #include "grit/theme_resources.h"
12 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
13 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
14 #import "ui/base/cocoa/nscolor_additions.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"
20 // Offset above vertical middle of page where contents of page start.
21 static const CGFloat kSadTabOffset = -64;
22 // Padding between icon and title.
23 static const CGFloat kIconTitleSpacing = 20;
24 // Padding between title and message.
25 static const CGFloat kTitleMessageSpacing = 15;
26 // Padding between message and link.
27 static const CGFloat kMessageLinkSpacing = 15;
28 // Paddings on left and right of page.
29 static const CGFloat kTabHorzMargin = 13;
30 // The width and height of the icon image view.
31 static const CGFloat kIconViewSize = 66;
33 @interface SadTabTextView : NSTextField
35 - (id)initWithView:(SadTabView*)view withText:(int)textIds;
39 @implementation SadTabTextView
41 - (id)initWithView:(SadTabView*)view withText:(int)textIds {
42 if (self = [super init]) {
43 [self setAlignment:NSCenterTextAlignment];
44 [self setStringValue:l10n_util::GetNSString(textIds)];
45 [self setEditable:NO];
47 [self setAutoresizingMask:
48 NSViewMinXMargin|NSViewWidthSizable|NSViewMaxXMargin|NSViewMinYMargin];
49 [view addSubview:self];
60 @implementation SadTabView
62 - (instancetype)initWithFrame:(NSRect)frame {
63 if ((self = [super initWithFrame:frame])) {
64 // Load resource for image and set it.
65 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
66 image_.reset([[NSImageView alloc]
67 initWithFrame:NSMakeRect(0, 0, kIconViewSize, kIconViewSize)]);
68 [image_ setImage:rb.GetNativeImageNamed(IDR_SAD_TAB).ToNSImage()];
69 [self addSubview:image_];
71 // Initialize background color.
72 NSColor* backgroundColor = [NSColor colorWithCalibratedWhite:247.0f/255.0f
74 [self setWantsLayer:YES];
75 [[self layer] setBackgroundColor:[backgroundColor cr_CGColor]];
78 title_.reset([[SadTabTextView alloc]
79 initWithView:self withText:IDS_SAD_TAB_TITLE]);
80 [title_ setFont:[NSFont systemFontOfSize:24]];
81 [title_ setBackgroundColor:backgroundColor];
82 [title_ setTextColor:[NSColor colorWithCalibratedWhite:51.0f/255.0f
85 // Set up the message.
86 message_.reset([[SadTabTextView alloc]
87 initWithView:self withText:IDS_SAD_TAB_MESSAGE]);
88 [message_ setFont:[NSFont systemFontOfSize:15]];
89 [message_ setBackgroundColor:backgroundColor];
90 [message_ setTextColor:[NSColor colorWithCalibratedWhite:100.0f/255.0f
93 [self initializeHelpText];
98 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
99 NSRect newBounds = [self bounds];
100 CGFloat maxWidth = NSWidth(newBounds) - (kTabHorzMargin * 2);
101 BOOL callSizeToFit = (messageSize_.width == 0);
103 // Set new frame origin for image.
104 NSRect iconFrame = [image_ frame];
105 CGFloat iconX = floorf((maxWidth - NSWidth(iconFrame)) / 2);
107 MIN(floorf((NSHeight(newBounds) - NSHeight(iconFrame)) / 2) -
109 NSHeight(newBounds) - NSHeight(iconFrame));
110 iconX = floorf(iconX);
111 iconY = floorf(iconY);
112 [image_ setFrameOrigin:NSMakePoint(iconX, iconY)];
114 // Set new frame origin for title.
117 NSRect titleFrame = [title_ frame];
118 CGFloat titleX = floorf((maxWidth - NSWidth(titleFrame)) / 2);
119 CGFloat titleY = iconY - kIconTitleSpacing - NSHeight(titleFrame);
120 [title_ setFrameOrigin:NSMakePoint(titleX, titleY)];
122 // Set new frame for message, wrapping or unwrapping the text if necessary.
124 [message_ sizeToFit];
125 messageSize_ = [message_ frame].size;
127 NSRect messageFrame = [message_ frame];
128 if (messageSize_.width > maxWidth) { // Need to wrap message.
129 [message_ setFrameSize:NSMakeSize(maxWidth, messageSize_.height)];
130 CGFloat heightChange =
131 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_];
132 messageFrame.size.width = maxWidth;
133 messageFrame.size.height = messageSize_.height + heightChange;
134 messageFrame.origin.x = kTabHorzMargin;
136 if (!callSizeToFit) {
137 [message_ sizeToFit];
138 messageFrame = [message_ frame];
140 messageFrame.origin.x = floorf((maxWidth - NSWidth(messageFrame)) / 2);
142 messageFrame.origin.y =
143 titleY - kTitleMessageSpacing - NSHeight(messageFrame);
144 [message_ setFrame:messageFrame];
146 // Set new frame for help text and link.
150 CGFloat helpHeight = [help_ frame].size.height;
151 [help_ setFrameSize:NSMakeSize(maxWidth, helpHeight)];
152 // Set new frame origin for link.
153 NSRect helpFrame = [help_ frame];
154 CGFloat helpX = floorf((maxWidth - NSWidth(helpFrame)) / 2);
156 NSMinY(messageFrame) - kMessageLinkSpacing - NSHeight(helpFrame);
157 [help_ setFrameOrigin:NSMakePoint(helpX, helpY)];
161 - (void)removeHelpText {
163 [help_ removeFromSuperview];
168 - (void)initializeHelpText {
169 // Programmatically create the help link. Note that the frame's initial
170 // height must be set for the programmatic resizing to work.
171 NSFont* helpFont = [message_ font];
172 NSRect helpFrame = NSMakeRect(0, 0, 1, [helpFont pointSize] + 4);
173 help_.reset([[HyperlinkTextView alloc] initWithFrame:helpFrame]);
174 [help_ setAutoresizingMask:
175 NSViewMinXMargin|NSViewWidthSizable|NSViewMaxXMargin|NSViewMinYMargin];
176 [help_ setDrawsBackground:YES];
177 [help_ setBackgroundColor:[message_ backgroundColor]];
178 [self addSubview:help_];
179 [help_ setDelegate:self];
181 // Get the help text and link.
182 size_t linkOffset = 0;
183 const base::string16 helpLink =
184 l10n_util::GetStringUTF16(IDS_SAD_TAB_HELP_LINK);
185 NSString* helpMessage(base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
186 IDS_SAD_TAB_HELP_MESSAGE, helpLink, &linkOffset)));
187 [help_ setMessage:helpMessage
189 messageColor:[message_ textColor]];
190 [help_ addLinkRange:NSMakeRange(linkOffset, helpLink.length())
192 linkColor:[message_ textColor]];
193 [help_ setAlignment:NSCenterTextAlignment];
196 // Called when someone clicks on the embedded link.
197 - (BOOL)textView:(NSTextView*)textView
198 clickedOnLink:(id)link
199 atIndex:(NSUInteger)charIndex {
200 [NSApp sendAction:@selector(openLearnMoreAboutCrashLink:) to:nil from:self];