Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.mm

Issue 2247493003: [Mac] Clean up SadTabView and let SadTabController provide its content (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adopt NSMake*, cast message_.cell to NSCell Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h" 5 #include "chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h"
6 6
7 #include <stddef.h>
8
9 #include "base/logging.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "chrome/common/url_constants.h"
12 #include "chrome/grit/generated_resources.h"
13 #include "components/grit/components_scaled_resources.h" 7 #include "components/grit/components_scaled_resources.h"
14 #include "components/strings/grit/components_strings.h"
15 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw eaker.h" 8 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw eaker.h"
16 #import "ui/base/cocoa/controls/blue_label_button.h" 9 #import "ui/base/cocoa/controls/blue_label_button.h"
17 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
18 #import "ui/base/cocoa/nscolor_additions.h" 10 #import "ui/base/cocoa/nscolor_additions.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/base/l10n/l10n_util_mac.h" 11 #include "ui/base/l10n/l10n_util_mac.h"
21 #include "ui/base/resource/resource_bundle.h" 12 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/image/image.h" 13
14 namespace {
23 15
24 // Maximum width used by page contents. 16 // Maximum width used by page contents.
25 static const CGFloat kMaxContainerWidth = 600; 17 const CGFloat kMaxContainerWidth = 600;
26 // Padding between icon and title. 18 // Padding between icon and title.
27 static const CGFloat kIconTitleSpacing = 40; 19 const CGFloat kIconTitleSpacing = 40;
28 // Padding between title and message. 20 // Padding between title and message.
29 static const CGFloat kTitleMessageSpacing = 18; 21 const CGFloat kTitleMessageSpacing = 18;
30 // Padding between message and link. 22 // Padding between message and link.
31 static const CGFloat kMessageLinkSpacing = 50; 23 const CGFloat kMessageLinkSpacing = 50;
32 // Padding between message and button. 24 // Padding between message and button.
33 static const CGFloat kMessageButtonSpacing = 44; 25 const CGFloat kMessageButtonSpacing = 44;
34 // Minimum margins on all sides. 26 // Minimum margins on all sides.
35 static const CGFloat kTabMargin = 13; 27 const CGFloat kTabMargin = 13;
36 // Maximum margin on top. 28 // Maximum margin on top.
37 static const CGFloat kMaxTopMargin = 130; 29 const CGFloat kMaxTopMargin = 130;
38 30
39 @interface SadTabTextView : NSTextField 31 NSTextField* MakeLabelTextField(NSRect frame) {
32 NSTextField* ret = [[[NSTextField alloc] initWithFrame:frame] autorelease];
33 ret.autoresizingMask = NSViewWidthSizable | NSViewMaxYMargin;
34 ret.editable = NO;
35 ret.drawsBackground = NO;
36 ret.bezeled = NO;
37 return ret;
38 }
40 39
41 - (id)initWithStringResourceID:(int)stringResourceID; 40 } // namespace
42 41
42 @interface SadTabContainerView : NSView
43 @end 43 @end
44 44
45 @implementation SadTabTextView 45 @implementation SadTabContainerView
46 - (BOOL)isFlipped {
47 return YES;
48 }
49 @end
46 50
47 - (id)initWithStringResourceID:(int)stringResourceID { 51 @interface SadTabView ()<NSTextViewDelegate>
48 if (self = [super init]) { 52 @end
49 base::scoped_nsobject<NSMutableParagraphStyle> style(
50 [[NSMutableParagraphStyle alloc] init]);
51 [style setLineSpacing:6];
52 base::scoped_nsobject<NSAttributedString> title([[NSAttributedString alloc]
53 initWithString:l10n_util::GetNSString(stringResourceID)
54 attributes:@{ NSParagraphStyleAttributeName : style }]);
55 [self setAttributedStringValue:title];
56 53
57 [self setAlignment:NSLeftTextAlignment]; 54 @implementation SadTabView {
58 [self setEditable:NO]; 55 NSView* container_;
59 [self setBezeled:NO]; 56 NSImageView* icon_;
60 [self setAutoresizingMask:NSViewWidthSizable|NSViewMaxYMargin]; 57 NSTextField* title_;
58 NSTextField* message_;
59 HyperlinkTextView* help_;
60 NSButton* button_;
61 }
62
63 @synthesize delegate = delegate_;
64
65 - (instancetype)initWithFrame:(NSRect)frame {
66 if ((self = [super initWithFrame:frame])) {
67 self.wantsLayer = YES;
68 self.layer.backgroundColor =
69 [NSColor colorWithCalibratedWhite:245.0f / 255.0f alpha:1.0].cr_CGColor;
70 container_ = [[SadTabContainerView new] autorelease];
71
72 NSImage* iconImage = ResourceBundle::GetSharedInstance()
73 .GetNativeImageNamed(IDR_CRASH_SAD_TAB)
74 .ToNSImage();
75 icon_ = [[NSImageView new] autorelease];
76 icon_.image = iconImage;
77 icon_.frameSize = iconImage.size;
78 icon_.autoresizingMask = NSViewMaxXMargin | NSViewMaxYMargin;
79 [container_ addSubview:icon_];
80
81 CGFloat width = self.bounds.size.width;
82 title_ = MakeLabelTextField(
83 NSMakeRect(0, NSMaxY(icon_.frame) + kIconTitleSpacing, width, 0));
84 title_.font = [NSFont systemFontOfSize:24];
85 title_.textColor =
86 [NSColor colorWithCalibratedWhite:38.0f / 255.0f alpha:1.0];
87 [title_ sizeToFit];
88 [container_ addSubview:title_];
89
90 message_ =
91 MakeLabelTextField(NSMakeRect(0, NSMaxY(title_.frame), width, 0));
92 ((NSCell*)message_.cell).wraps = YES;
Avi (use Gerrit) 2016/08/14 04:54:28 base::mac::ObjCCast
Sidney San Martín 2016/08/15 03:40:29 Done. ObjCCast really surprises me though — it ret
Avi (use Gerrit) 2016/08/15 03:43:59 Interesting way of thinking about it. Talk to Mark
erikchen 2016/08/15 21:03:03 I think that downcasting is an appropriate use cas
93 message_.font = [NSFont systemFontOfSize:14];
94 message_.textColor =
95 [NSColor colorWithCalibratedWhite:81.0f / 255.0f alpha:1.0];
96 [container_ addSubview:message_];
97
98 help_ = [[[HyperlinkTextView alloc]
99 initWithFrame:NSMakeRect(0, 0, 1, message_.font.pointSize + 4)]
100 autorelease];
101 help_.delegate = self;
102 help_.autoresizingMask = NSViewWidthSizable | NSViewMaxYMargin;
103 help_.textContainer.lineFragmentPadding = 2; // To align with message_.
104 [container_ addSubview:help_];
105
106 button_ = [[BlueLabelButton new] autorelease];
107 button_.target = self;
108 button_.action = @selector(buttonClicked);
109 [container_ addSubview:button_];
110
111 [self addSubview:container_];
61 } 112 }
62 return self; 113 return self;
63 } 114 }
64
65 - (BOOL)isOpaque {
66 return YES;
67 }
68
69 @end
70
71 @interface SadTabContainerView : NSView<NSTextViewDelegate> {
72 @private
73 base::scoped_nsobject<NSImageView> image_;
74 base::scoped_nsobject<NSTextField> title_;
75 base::scoped_nsobject<NSTextField> message_;
76 base::scoped_nsobject<HyperlinkTextView> help_;
77 base::scoped_nsobject<NSButton> button_;
78 }
79
80 - (instancetype)initWithBackgroundColor:(NSColor*)backgroundColor;
81
82 @property(readonly,nonatomic) NSButton* reloadButton;
83
84 // The height to fit the content elements within the current width.
85 @property(readonly,nonatomic) CGFloat contentHeight;
86
87 @end
88
89 @implementation SadTabContainerView
90
91 - (instancetype)initWithBackgroundColor:(NSColor*)backgroundColor {
92 if ((self = [super initWithFrame:NSZeroRect])) {
93 // Load resource for image and set it.
94 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
95 NSImage* iconImage = rb.GetNativeImageNamed(IDR_CRASH_SAD_TAB).ToNSImage();
96 NSRect imageFrame = NSZeroRect;
97 imageFrame.size = [iconImage size];
98 image_.reset([[NSImageView alloc] initWithFrame:imageFrame]);
99 [image_ setImage:iconImage];
100 [image_ setAutoresizingMask:NSViewMaxXMargin|NSViewMaxYMargin];
101 [self addSubview:image_];
102
103 // Set up the title.
104 title_.reset(
105 [[SadTabTextView alloc] initWithStringResourceID:IDS_SAD_TAB_TITLE]);
106 [title_ setFont:[NSFont systemFontOfSize:24]];
107 [title_ setBackgroundColor:backgroundColor];
108 [title_ setTextColor:[NSColor colorWithCalibratedWhite:38.0f/255.0f
109 alpha:1.0]];
110 [title_ sizeToFit];
111 [title_ setFrameOrigin:
112 NSMakePoint(0, NSMaxY(imageFrame) + kIconTitleSpacing)];
113 [self addSubview:title_];
114
115 // Set up the message.
116 message_.reset(
117 [[SadTabTextView alloc] initWithStringResourceID:IDS_SAD_TAB_MESSAGE]);
118 [message_ setFont:[NSFont systemFontOfSize:14]];
119 [message_ setBackgroundColor:backgroundColor];
120 [message_ setTextColor:[NSColor colorWithCalibratedWhite:81.0f/255.0f
121 alpha:1.0]];
122 [message_ setFrameOrigin:
123 NSMakePoint(0, NSMaxY([title_ frame]) + kTitleMessageSpacing)];
124 [self addSubview:message_];
125
126 [self initializeHelpText];
127
128 button_.reset([[BlueLabelButton alloc] init]);
129 [button_ setTitle:l10n_util::GetNSString(IDS_SAD_TAB_RELOAD_LABEL)];
130 [button_ sizeToFit];
131 [button_ setTarget:self];
132 [button_ setAction:@selector(reloadPage:)];
133 [self addSubview:button_];
134 }
135 return self;
136 }
137 115
138 - (BOOL)isFlipped { 116 - (BOOL)isFlipped {
139 return YES; 117 return YES;
140 } 118 }
141 119
142 - (NSButton*)reloadButton {
143 return button_;
144 }
145
146 - (CGFloat)contentHeight {
147 return NSMaxY([button_ frame]);
148 }
149
150 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize { 120 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
151 [super resizeSubviewsWithOldSize:oldSize]; 121 [super resizeSubviewsWithOldSize:oldSize];
152 122
123 NSSize size = self.bounds.size;
124 NSSize containerSize = NSMakeSize(
125 std::min(size.width - 2 * kTabMargin, kMaxContainerWidth), size.height);
126
127 // Set the container's size first because text wrapping depends on its width.
128 container_.frameSize = containerSize;
129
153 // |message_| can wrap to variable number of lines. 130 // |message_| can wrap to variable number of lines.
154 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_]; 131 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_];
155 132
156 [help_ setFrameOrigin: 133 message_.frameOrigin =
157 NSMakePoint(0, NSMaxY([message_ frame]) + kMessageLinkSpacing)]; 134 NSMakePoint(0, NSMaxY(title_.frame) + kTitleMessageSpacing);
135 help_.frameOrigin =
136 NSMakePoint(0, NSMaxY(message_.frame) + kMessageLinkSpacing);
158 137
159 [button_ setFrameOrigin: 138 button_.frameOrigin =
160 NSMakePoint(NSMaxX([self bounds]) - NSWidth([button_ frame]), 139 NSMakePoint(containerSize.width - NSWidth(button_.bounds),
161 NSMaxY([message_ frame]) + kMessageButtonSpacing)]; 140 NSMaxY(message_.frame) + kMessageButtonSpacing);
141
142 containerSize.height = NSMaxY(button_.frame);
143 container_.frameSize = containerSize;
144
145 // Center. Top margin is must be between kTabMargin and kMaxTopMargin.
146 container_.frameOrigin = NSMakePoint(
147 floor((size.width - containerSize.width) / 2),
148 std::min(kMaxTopMargin,
149 std::max(kTabMargin,
150 size.height - containerSize.height - kTabMargin)));
162 } 151 }
163 152
164 - (void)initializeHelpText { 153 - (void)setTitle:(int)title {
165 // Programmatically create the help link. Note that the frame's initial 154 NSMutableParagraphStyle* style = [[NSMutableParagraphStyle new] autorelease];
166 // height must be set for the programmatic resizing to work. 155 style.lineSpacing = 6;
167 NSFont* helpFont = [message_ font];
168 NSRect helpFrame = NSMakeRect(0, 0, 1, [helpFont pointSize] + 4);
169 help_.reset([[HyperlinkTextView alloc] initWithFrame:helpFrame]);
170 [help_ setAutoresizingMask:NSViewWidthSizable|NSViewMaxYMargin];
171 [help_ setDrawsBackground:YES];
172 [help_ setBackgroundColor:[message_ backgroundColor]];
173 [[help_ textContainer] setLineFragmentPadding:2]; // To align with message_.
174 [self addSubview:help_];
175 [help_ setDelegate:self];
176 156
177 // Get the help text and link. 157 title_.attributedStringValue = [[[NSAttributedString alloc]
178 size_t linkOffset = 0; 158 initWithString:l10n_util::GetNSString(title)
179 const base::string16 helpLink = 159 attributes:@{NSParagraphStyleAttributeName : style}] autorelease];
180 l10n_util::GetStringUTF16(IDS_SAD_TAB_LEARN_MORE_LINK); 160 }
181 NSString* helpMessage(base::SysUTF16ToNSString(helpLink)); 161
182 [help_ setMessage:helpMessage 162 - (void)setMessage:(int)message {
183 withFont:helpFont 163 message_.stringValue = l10n_util::GetNSString(message);
184 messageColor:[message_ textColor]]; 164 }
185 [help_ addLinkRange:NSMakeRange(linkOffset, helpLink.length()) 165
186 withURL:@(chrome::kCrashReasonURL) 166 - (void)setButtonTitle:(int)buttonTitle {
187 linkColor:[message_ textColor]]; 167 button_.title = l10n_util::GetNSString(buttonTitle);
188 [help_ setAlignment:NSLeftTextAlignment]; 168 [button_ sizeToFit];
169 }
170
171 - (void)setHelpLinkTitle:(int)helpLinkTitle URL:(NSString*)url {
172 NSString* title = l10n_util::GetNSString(helpLinkTitle);
173 [help_ setMessage:title
174 withFont:message_.font
175 messageColor:message_.textColor];
176 [help_ addLinkRange:NSMakeRange(0, title.length)
177 withURL:url
178 linkColor:message_.textColor];
189 [help_ sizeToFit]; 179 [help_ sizeToFit];
190 } 180 }
191 181
182 - (void)buttonClicked {
183 [delegate_ sadTabViewButtonClicked:self];
184 }
185
192 // Called when someone clicks on the embedded link. 186 // Called when someone clicks on the embedded link.
193 - (BOOL)textView:(NSTextView*)textView 187 - (BOOL)textView:(NSTextView*)textView
194 clickedOnLink:(id)link 188 clickedOnLink:(id)link
195 atIndex:(NSUInteger)charIndex { 189 atIndex:(NSUInteger)charIndex {
196 [NSApp sendAction:@selector(openLearnMoreAboutCrashLink:) to:nil from:self]; 190 [delegate_ sadTabView:self helpLinkClickedWithURL:(NSString*)link];
197 return YES; 191 return YES;
198 } 192 }
199 193
200 @end 194 @end
201
202 @implementation SadTabView
203
204 + (NSColor*)backgroundColor {
205 return [NSColor colorWithCalibratedWhite:245.0f/255.0f alpha:1.0];
206 }
207
208 - (instancetype)initWithFrame:(NSRect)frame {
209 if ((self = [super initWithFrame:frame])) {
210 [self setWantsLayer:YES];
211
212 container_.reset([[SadTabContainerView alloc]
213 initWithBackgroundColor:[SadTabView backgroundColor]]);
214 [self addSubview:container_];
215 }
216 return self;
217 }
218
219 - (CALayer*)makeBackingLayer {
220 CALayer* layer = [super makeBackingLayer];
221 [layer setBackgroundColor:[[SadTabView backgroundColor] cr_CGColor]];
222 return layer;
223 }
224
225 - (BOOL)isFlipped {
226 return YES;
227 }
228
229 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
230 NSRect bounds = [self bounds];
231
232 // Set the container size first because its contentHeight will depend on its
233 // width.
234 NSSize frameSize = NSMakeSize(
235 std::min(NSWidth(bounds) - 2 * kTabMargin, kMaxContainerWidth),
236 NSHeight(bounds));
237 [container_ setFrameSize:frameSize];
238
239 // Center horizontally.
240 // Top margin is at least kTabMargin and at most kMaxTopMargin.
241 [container_ setFrameOrigin:NSMakePoint(
242 floor((NSWidth(bounds) - frameSize.width) / 2),
243 std::min(kMaxTopMargin, std::max(kTabMargin,
244 NSHeight(bounds) - [container_ contentHeight] - kTabMargin)))];
245 }
246
247 - (NSButton*)reloadButton {
248 return [container_ reloadButton];
249 }
250
251 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/tab_contents/sad_tab_view_cocoa.h ('k') | ui/gfx/test/ui_cocoa_test_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698