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

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

Issue 2261793002: Bring the feedback button to the Mac sad tab (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Address second wave of comments, turn off feedback in non-Chrome builds Created 4 years, 3 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 #import "base/mac/foundation_util.h" 7 #import "base/mac/foundation_util.h"
8 #include "components/grit/components_scaled_resources.h" 8 #include "components/grit/components_scaled_resources.h"
9 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw eaker.h" 9 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw eaker.h"
10 #import "ui/base/cocoa/controls/blue_label_button.h" 10 #import "ui/base/cocoa/controls/blue_label_button.h"
11 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
11 #import "ui/base/cocoa/nscolor_additions.h" 12 #import "ui/base/cocoa/nscolor_additions.h"
12 #include "ui/base/l10n/l10n_util_mac.h" 13 #include "ui/base/l10n/l10n_util_mac.h"
13 #include "ui/base/resource/resource_bundle.h" 14 #include "ui/base/resource/resource_bundle.h"
14 15
15 namespace { 16 namespace {
16 17
17 // Maximum width used by page contents. 18 // Maximum width used by page contents.
18 const CGFloat kMaxContainerWidth = 600; 19 const CGFloat kMaxContainerWidth = 600;
19 // Padding between icon and title. 20 // Padding between icon and title.
20 const CGFloat kIconTitleSpacing = 40; 21 const CGFloat kIconTitleSpacing = 40;
21 // Padding between title and message. 22 // Padding between title and message.
22 const CGFloat kTitleMessageSpacing = 18; 23 const CGFloat kTitleMessageSpacing = 18;
23 // Padding between message and link. 24 // Padding between message and link.
24 const CGFloat kMessageLinkSpacing = 50; 25 const CGFloat kMessageLinkSpacing = 50;
25 // Padding between message and button. 26 // Padding between message and button.
26 const CGFloat kMessageButtonSpacing = 44; 27 const CGFloat kMessageButtonSpacing = 44;
27 // Minimum margins on all sides. 28 // Minimum margins on all sides.
28 const CGFloat kTabMargin = 13; 29 const CGFloat kTabMargin = 13;
29 // Maximum margin on top. 30 // Maximum margin on top.
30 const CGFloat kMaxTopMargin = 130; 31 const CGFloat kMaxTopMargin = 130;
31 32
32 NSTextField* MakeLabelTextField(NSRect frame) { 33 NSTextField* MakeLabelTextField(NSRect frame) {
34 // Not a scoped_nsobject for easy property access.
33 NSTextField* ret = [[[NSTextField alloc] initWithFrame:frame] autorelease]; 35 NSTextField* ret = [[[NSTextField alloc] initWithFrame:frame] autorelease];
34 ret.autoresizingMask = NSViewWidthSizable | NSViewMaxYMargin; 36 ret.autoresizingMask = NSViewWidthSizable;
35 ret.editable = NO; 37 ret.editable = NO;
36 ret.drawsBackground = NO; 38 ret.drawsBackground = NO;
37 ret.bezeled = NO; 39 ret.bezeled = NO;
38 return ret; 40 return ret;
39 } 41 }
40 42
41 } // namespace 43 } // namespace
42 44
43 @interface SadTabContainerView : NSView 45 @interface SadTabContainerView : NSView
44 @end 46 @end
45 47
46 @implementation SadTabContainerView 48 @implementation SadTabContainerView
47 - (BOOL)isFlipped { 49 - (BOOL)isFlipped {
48 return YES; 50 return YES;
49 } 51 }
50 @end 52 @end
51 53
52 @interface SadTabView ()<NSTextViewDelegate> 54 @interface SadTabView ()<NSTextViewDelegate>
53 @end 55 @end
54 56
55 @implementation SadTabView { 57 @implementation SadTabView {
56 NSView* container_; 58 NSView* container_;
57 NSImageView* icon_;
58 NSTextField* title_;
59 NSTextField* message_; 59 NSTextField* message_;
60 HyperlinkTextView* help_; 60 HyperlinkTextView* help_;
61 NSButton* button_; 61 NSButton* button_;
62 chrome::SadTab* sadTab_;
62 } 63 }
63 64
64 @synthesize delegate = delegate_; 65 - (instancetype)initWithFrame:(NSRect)frame sadTab:(chrome::SadTab*)sadTab {
66 if ((self = [super initWithFrame:frame])) {
67 sadTab_ = sadTab;
65 68
66 - (instancetype)initWithFrame:(NSRect)frame {
67 if ((self = [super initWithFrame:frame])) {
68 self.wantsLayer = YES; 69 self.wantsLayer = YES;
69 self.layer.backgroundColor = 70 self.layer.backgroundColor =
70 [NSColor colorWithCalibratedWhite:245.0f / 255.0f alpha:1.0].cr_CGColor; 71 [NSColor colorWithCalibratedWhite:245.0f / 255.0f alpha:1.0].cr_CGColor;
71 container_ = [[SadTabContainerView new] autorelease]; 72 container_ = [[SadTabContainerView new] autorelease];
72 73
73 NSImage* iconImage = ResourceBundle::GetSharedInstance() 74 NSImage* iconImage = ResourceBundle::GetSharedInstance()
74 .GetNativeImageNamed(IDR_CRASH_SAD_TAB) 75 .GetNativeImageNamed(IDR_CRASH_SAD_TAB)
75 .ToNSImage(); 76 .ToNSImage();
76 icon_ = [[NSImageView new] autorelease]; 77 NSImageView* icon = [[NSImageView new] autorelease];
77 icon_.image = iconImage; 78 icon.image = iconImage;
78 icon_.frameSize = iconImage.size; 79 icon.frameSize = iconImage.size;
79 icon_.autoresizingMask = NSViewMaxXMargin | NSViewMaxYMargin; 80 [container_ addSubview:icon];
80 [container_ addSubview:icon_];
81 81
82 CGFloat width = self.bounds.size.width; 82 NSTextField* title = MakeLabelTextField(
83 title_ = MakeLabelTextField( 83 NSMakeRect(0, NSMaxY(icon.frame) + kIconTitleSpacing, 0, 0));
84 NSMakeRect(0, NSMaxY(icon_.frame) + kIconTitleSpacing, width, 0)); 84 title.font = [NSFont systemFontOfSize:24];
85 title_.font = [NSFont systemFontOfSize:24]; 85 title.textColor =
86 title_.textColor =
87 [NSColor colorWithCalibratedWhite:38.0f / 255.0f alpha:1.0]; 86 [NSColor colorWithCalibratedWhite:38.0f / 255.0f alpha:1.0];
88 [title_ sizeToFit];
89 [container_ addSubview:title_];
90 87
91 message_ = 88 NSMutableParagraphStyle* titleStyle =
92 MakeLabelTextField(NSMakeRect(0, NSMaxY(title_.frame), width, 0)); 89 [[NSMutableParagraphStyle new] autorelease];
90 titleStyle.lineSpacing = 6;
91 title.attributedStringValue = [[[NSAttributedString alloc]
92 initWithString:l10n_util::GetNSString(sadTab->GetTitle())
93 attributes:@{NSParagraphStyleAttributeName : titleStyle}]
94 autorelease];
95
96 [title sizeToFit];
97 [container_ addSubview:title];
98
99 NSFont* messageFont = [NSFont systemFontOfSize:14];
100 NSColor* messageColor =
101 [NSColor colorWithCalibratedWhite:81.0f / 255.0f alpha:1.0];
102
103 message_ = MakeLabelTextField(NSMakeRect(0, NSMaxY(title.frame), 0, 0));
104 message_.frameOrigin =
105 NSMakePoint(0, NSMaxY(title.frame) + kTitleMessageSpacing);
93 base::mac::ObjCCast<NSCell>(message_.cell).wraps = YES; 106 base::mac::ObjCCast<NSCell>(message_.cell).wraps = YES;
94 message_.font = [NSFont systemFontOfSize:14]; 107 message_.font = messageFont;
95 message_.textColor = 108 message_.textColor = messageColor;
96 [NSColor colorWithCalibratedWhite:81.0f / 255.0f alpha:1.0]; 109 message_.stringValue = l10n_util::GetNSString(sadTab->GetMessage());
97 [container_ addSubview:message_]; 110 [container_ addSubview:message_];
98 111
112 NSString* helpLinkTitle =
113 l10n_util::GetNSString(sadTab->GetHelpLinkTitle());
99 help_ = [[[HyperlinkTextView alloc] 114 help_ = [[[HyperlinkTextView alloc]
100 initWithFrame:NSMakeRect(0, 0, 1, message_.font.pointSize + 4)] 115 initWithFrame:NSMakeRect(0, 0, 1, message_.font.pointSize + 4)]
101 autorelease]; 116 autorelease];
102 help_.delegate = self; 117 help_.delegate = self;
103 help_.autoresizingMask = NSViewWidthSizable | NSViewMaxYMargin; 118 help_.autoresizingMask = NSViewWidthSizable;
104 help_.textContainer.lineFragmentPadding = 2; // To align with message_. 119 help_.textContainer.lineFragmentPadding = 2; // To align with message_.
120 [help_ setMessage:helpLinkTitle
121 withFont:messageFont
122 messageColor:messageColor];
123 [help_ addLinkRange:NSMakeRange(0, helpLinkTitle.length)
124 withURL:@(sadTab->GetHelpLinkURL())
125 linkColor:messageColor];
126 [help_ sizeToFit];
105 [container_ addSubview:help_]; 127 [container_ addSubview:help_];
106 128
107 button_ = [[BlueLabelButton new] autorelease]; 129 button_ = [[BlueLabelButton new] autorelease];
108 button_.target = self; 130 button_.target = self;
109 button_.action = @selector(buttonClicked); 131 button_.action = @selector(buttonClicked);
132 button_.title = l10n_util::GetNSString(sadTab->GetButtonTitle());
133 [button_ sizeToFit];
110 [container_ addSubview:button_]; 134 [container_ addSubview:button_];
111 135
112 [self addSubview:container_]; 136 [self addSubview:container_];
137 [self resizeSubviewsWithOldSize:self.bounds.size];
113 } 138 }
114 return self; 139 return self;
115 } 140 }
116 141
142 - (BOOL)isOpaque {
143 return YES;
144 }
145
117 - (BOOL)isFlipped { 146 - (BOOL)isFlipped {
118 return YES; 147 return YES;
119 } 148 }
120 149
150 - (void)updateLayer {
151 // Currently, updateLayer is only called once. If that changes, a DCHECK in
152 // SadTab::RecordFirstPaint will pipe up and we should add a guard here.
153 sadTab_->RecordFirstPaint();
154 }
155
121 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize { 156 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
122 [super resizeSubviewsWithOldSize:oldSize]; 157 [super resizeSubviewsWithOldSize:oldSize];
123 158
124 NSSize size = self.bounds.size; 159 NSSize size = self.bounds.size;
125 NSSize containerSize = NSMakeSize( 160 NSSize containerSize = NSMakeSize(
126 std::min(size.width - 2 * kTabMargin, kMaxContainerWidth), size.height); 161 std::min(size.width - 2 * kTabMargin, kMaxContainerWidth), size.height);
127 162
128 // Set the container's size first because text wrapping depends on its width. 163 // Set the container's size first because text wrapping depends on its width.
129 container_.frameSize = containerSize; 164 container_.frameSize = containerSize;
130 165
131 // |message_| can wrap to variable number of lines. 166 // |message_| can wrap to variable number of lines.
132 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_]; 167 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_];
133 168
134 message_.frameOrigin =
135 NSMakePoint(0, NSMaxY(title_.frame) + kTitleMessageSpacing);
136 help_.frameOrigin = 169 help_.frameOrigin =
137 NSMakePoint(0, NSMaxY(message_.frame) + kMessageLinkSpacing); 170 NSMakePoint(0, NSMaxY(message_.frame) + kMessageLinkSpacing);
138 171
139 button_.frameOrigin = 172 button_.frameOrigin =
140 NSMakePoint(containerSize.width - NSWidth(button_.bounds), 173 NSMakePoint(containerSize.width - NSWidth(button_.bounds),
141 NSMaxY(message_.frame) + kMessageButtonSpacing); 174 NSMaxY(message_.frame) + kMessageButtonSpacing);
142 175
143 containerSize.height = NSMaxY(button_.frame); 176 containerSize.height = NSMaxY(button_.frame);
144 container_.frameSize = containerSize; 177 container_.frameSize = containerSize;
145 178
146 // Center. Top margin is must be between kTabMargin and kMaxTopMargin. 179 // Center. Top margin is must be between kTabMargin and kMaxTopMargin.
147 container_.frameOrigin = NSMakePoint( 180 container_.frameOrigin = NSMakePoint(
148 floor((size.width - containerSize.width) / 2), 181 floor((size.width - containerSize.width) / 2),
149 std::min(kMaxTopMargin, 182 std::min(kMaxTopMargin,
150 std::max(kTabMargin, 183 std::max(kTabMargin,
151 size.height - containerSize.height - kTabMargin))); 184 size.height - containerSize.height - kTabMargin)));
152 } 185 }
153 186
154 - (void)setTitle:(int)title {
155 NSMutableParagraphStyle* style = [[NSMutableParagraphStyle new] autorelease];
156 style.lineSpacing = 6;
157
158 title_.attributedStringValue = [[[NSAttributedString alloc]
159 initWithString:l10n_util::GetNSString(title)
160 attributes:@{NSParagraphStyleAttributeName : style}] autorelease];
161 }
162
163 - (void)setMessage:(int)message {
164 message_.stringValue = l10n_util::GetNSString(message);
165 }
166
167 - (void)setButtonTitle:(int)buttonTitle {
168 button_.title = l10n_util::GetNSString(buttonTitle);
169 [button_ sizeToFit];
170 }
171
172 - (void)setHelpLinkTitle:(int)helpLinkTitle URL:(NSString*)url {
173 NSString* title = l10n_util::GetNSString(helpLinkTitle);
174 [help_ setMessage:title
175 withFont:message_.font
176 messageColor:message_.textColor];
177 [help_ addLinkRange:NSMakeRange(0, title.length)
178 withURL:url
179 linkColor:message_.textColor];
180 [help_ sizeToFit];
181 }
182
183 - (void)buttonClicked { 187 - (void)buttonClicked {
184 [delegate_ sadTabViewButtonClicked:self]; 188 sadTab_->PerformAction(chrome::SadTab::Action::BUTTON);
185 } 189 }
186 190
187 // Called when someone clicks on the embedded link. 191 // Called when someone clicks on the embedded link.
188 - (BOOL)textView:(NSTextView*)textView 192 - (BOOL)textView:(NSTextView*)textView
189 clickedOnLink:(id)link 193 clickedOnLink:(id)link
190 atIndex:(NSUInteger)charIndex { 194 atIndex:(NSUInteger)charIndex {
191 [delegate_ sadTabView:self helpLinkClickedWithURL:(NSString*)link]; 195 sadTab_->PerformAction(chrome::SadTab::Action::HELP_LINK);
192 return YES; 196 return YES;
193 } 197 }
194 198
199 - (NSRange)textView:(NSTextView*)textView
200 willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange
201 toCharacterRange:(NSRange)newSelectedCharRange {
202 return NSMakeRange(0, 0);
203 }
204
195 @end 205 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698