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

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: Ditch a pointless |explicit|, add a comment on SadTabView ownership. 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) {
33 NSTextField* ret = [[[NSTextField alloc] initWithFrame:frame] autorelease]; 34 NSTextField* ret = [[[NSTextField alloc] initWithFrame:frame] autorelease];
34 ret.autoresizingMask = NSViewWidthSizable | NSViewMaxYMargin; 35 ret.autoresizingMask = NSViewWidthSizable;
35 ret.editable = NO; 36 ret.editable = NO;
36 ret.drawsBackground = NO; 37 ret.drawsBackground = NO;
37 ret.bezeled = NO; 38 ret.bezeled = NO;
38 return ret; 39 return ret;
39 } 40 }
40 41
41 } // namespace 42 } // namespace
42 43
43 @interface SadTabContainerView : NSView 44 @interface SadTabContainerView : NSView
44 @end 45 @end
45 46
46 @implementation SadTabContainerView 47 @implementation SadTabContainerView
47 - (BOOL)isFlipped { 48 - (BOOL)isFlipped {
48 return YES; 49 return YES;
49 } 50 }
50 @end 51 @end
51 52
52 @interface SadTabView ()<NSTextViewDelegate> 53 @interface SadTabView ()<NSTextViewDelegate>
53 @end 54 @end
54 55
55 @implementation SadTabView { 56 @implementation SadTabView {
56 NSView* container_; 57 NSView* container_;
57 NSImageView* icon_;
58 NSTextField* title_;
59 NSTextField* message_; 58 NSTextField* message_;
60 HyperlinkTextView* help_; 59 HyperlinkTextView* help_;
61 NSButton* button_; 60 NSButton* button_;
61 chrome::SadTab* sadTab_;
62 } 62 }
63 63
64 @synthesize delegate = delegate_; 64 - (instancetype)initWithFrame:(NSRect)frame sadTab:(chrome::SadTab*)sadTab {
65 if ((self = [super initWithFrame:frame])) {
66 sadTab_ = sadTab;
65 67
66 - (instancetype)initWithFrame:(NSRect)frame {
67 if ((self = [super initWithFrame:frame])) {
68 self.wantsLayer = YES; 68 self.wantsLayer = YES;
69 self.layer.backgroundColor = 69 self.layer.backgroundColor =
70 [NSColor colorWithCalibratedWhite:245.0f / 255.0f alpha:1.0].cr_CGColor; 70 [NSColor colorWithCalibratedWhite:245.0f / 255.0f alpha:1.0].cr_CGColor;
71 container_ = [[SadTabContainerView new] autorelease]; 71 container_ = [[SadTabContainerView new] autorelease];
72 72
73 NSImage* iconImage = ResourceBundle::GetSharedInstance() 73 NSImage* iconImage = ResourceBundle::GetSharedInstance()
74 .GetNativeImageNamed(IDR_CRASH_SAD_TAB) 74 .GetNativeImageNamed(IDR_CRASH_SAD_TAB)
75 .ToNSImage(); 75 .ToNSImage();
76 icon_ = [[NSImageView new] autorelease]; 76 NSImageView* icon = [[NSImageView new] autorelease];
77 icon_.image = iconImage; 77 icon.image = iconImage;
78 icon_.frameSize = iconImage.size; 78 icon.frameSize = iconImage.size;
79 icon_.autoresizingMask = NSViewMaxXMargin | NSViewMaxYMargin; 79 [container_ addSubview:icon];
80 [container_ addSubview:icon_];
81 80
82 CGFloat width = self.bounds.size.width; 81 NSTextField* title = MakeLabelTextField(
83 title_ = MakeLabelTextField( 82 NSMakeRect(0, NSMaxY(icon.frame) + kIconTitleSpacing, 0, 0));
84 NSMakeRect(0, NSMaxY(icon_.frame) + kIconTitleSpacing, width, 0)); 83 title.font = [NSFont systemFontOfSize:24];
85 title_.font = [NSFont systemFontOfSize:24]; 84 title.textColor =
86 title_.textColor =
87 [NSColor colorWithCalibratedWhite:38.0f / 255.0f alpha:1.0]; 85 [NSColor colorWithCalibratedWhite:38.0f / 255.0f alpha:1.0];
88 [title_ sizeToFit];
89 [container_ addSubview:title_];
90 86
91 message_ = 87 NSMutableParagraphStyle* titleStyle =
Nico 2016/09/08 17:12:59 nit: I think we slightly prefer local scoped_nsobj
Sidney San Martín 2016/09/09 01:36:00 Yeah, you caught me. I avoided scoped_nsobject bec
Nico 2016/09/09 01:48:42 Oh hm, that's a good point. Maybe just add `// Not
Sidney San Martín 2016/09/09 15:39:44 OK. I threw in a comment for now and ask around/as
92 MakeLabelTextField(NSMakeRect(0, NSMaxY(title_.frame), width, 0)); 88 [[NSMutableParagraphStyle new] autorelease];
89 titleStyle.lineSpacing = 6;
90 title.attributedStringValue = [[[NSAttributedString alloc]
91 initWithString:l10n_util::GetNSString(sadTab->GetTitle())
92 attributes:@{NSParagraphStyleAttributeName : titleStyle}]
93 autorelease];
94
95 [title sizeToFit];
96 [container_ addSubview:title];
97
98 NSFont* messageFont = [NSFont systemFontOfSize:14];
99 NSColor* messageColor =
100 [NSColor colorWithCalibratedWhite:81.0f / 255.0f alpha:1.0];
101
102 message_ = MakeLabelTextField(NSMakeRect(0, NSMaxY(title.frame), 0, 0));
103 message_.frameOrigin =
104 NSMakePoint(0, NSMaxY(title.frame) + kTitleMessageSpacing);
93 base::mac::ObjCCast<NSCell>(message_.cell).wraps = YES; 105 base::mac::ObjCCast<NSCell>(message_.cell).wraps = YES;
94 message_.font = [NSFont systemFontOfSize:14]; 106 message_.font = messageFont;
95 message_.textColor = 107 message_.textColor = messageColor;
96 [NSColor colorWithCalibratedWhite:81.0f / 255.0f alpha:1.0]; 108 message_.stringValue = l10n_util::GetNSString(sadTab->GetMessage());
97 [container_ addSubview:message_]; 109 [container_ addSubview:message_];
98 110
111 NSString* helpLinkTitle =
112 l10n_util::GetNSString(sadTab->GetHelpLinkTitle());
99 help_ = [[[HyperlinkTextView alloc] 113 help_ = [[[HyperlinkTextView alloc]
100 initWithFrame:NSMakeRect(0, 0, 1, message_.font.pointSize + 4)] 114 initWithFrame:NSMakeRect(0, 0, 1, message_.font.pointSize + 4)]
101 autorelease]; 115 autorelease];
102 help_.delegate = self; 116 help_.delegate = self;
103 help_.autoresizingMask = NSViewWidthSizable | NSViewMaxYMargin; 117 help_.autoresizingMask = NSViewWidthSizable;
104 help_.textContainer.lineFragmentPadding = 2; // To align with message_. 118 help_.textContainer.lineFragmentPadding = 2; // To align with message_.
119 [help_ setMessage:helpLinkTitle
120 withFont:messageFont
121 messageColor:messageColor];
122 [help_ addLinkRange:NSMakeRange(0, helpLinkTitle.length)
123 withURL:@(sadTab->GetHelpLinkURL())
124 linkColor:messageColor];
125 [help_ sizeToFit];
105 [container_ addSubview:help_]; 126 [container_ addSubview:help_];
106 127
107 button_ = [[BlueLabelButton new] autorelease]; 128 button_ = [[BlueLabelButton new] autorelease];
108 button_.target = self; 129 button_.target = self;
109 button_.action = @selector(buttonClicked); 130 button_.action = @selector(buttonClicked);
131 button_.title = l10n_util::GetNSString(sadTab->GetButtonTitle());
132 [button_ sizeToFit];
110 [container_ addSubview:button_]; 133 [container_ addSubview:button_];
111 134
112 [self addSubview:container_]; 135 [self addSubview:container_];
136 [self resizeSubviewsWithOldSize:self.bounds.size];
113 } 137 }
114 return self; 138 return self;
115 } 139 }
116 140
141 - (BOOL)isOpaque {
142 return YES;
143 }
144
117 - (BOOL)isFlipped { 145 - (BOOL)isFlipped {
118 return YES; 146 return YES;
119 } 147 }
120 148
149 - (void)updateLayer {
150 // Currently, updateLayer is only called once. If that changes, a DCHECK in
151 // SadTab::RecordFirstPaint will pipe up and we should add a guard here.
152 sadTab_->RecordFirstPaint();
153 }
154
121 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize { 155 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
122 [super resizeSubviewsWithOldSize:oldSize]; 156 [super resizeSubviewsWithOldSize:oldSize];
123 157
124 NSSize size = self.bounds.size; 158 NSSize size = self.bounds.size;
125 NSSize containerSize = NSMakeSize( 159 NSSize containerSize = NSMakeSize(
126 std::min(size.width - 2 * kTabMargin, kMaxContainerWidth), size.height); 160 std::min(size.width - 2 * kTabMargin, kMaxContainerWidth), size.height);
127 161
128 // Set the container's size first because text wrapping depends on its width. 162 // Set the container's size first because text wrapping depends on its width.
129 container_.frameSize = containerSize; 163 container_.frameSize = containerSize;
130 164
131 // |message_| can wrap to variable number of lines. 165 // |message_| can wrap to variable number of lines.
132 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_]; 166 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_];
133 167
134 message_.frameOrigin =
135 NSMakePoint(0, NSMaxY(title_.frame) + kTitleMessageSpacing);
136 help_.frameOrigin = 168 help_.frameOrigin =
137 NSMakePoint(0, NSMaxY(message_.frame) + kMessageLinkSpacing); 169 NSMakePoint(0, NSMaxY(message_.frame) + kMessageLinkSpacing);
138 170
139 button_.frameOrigin = 171 button_.frameOrigin =
140 NSMakePoint(containerSize.width - NSWidth(button_.bounds), 172 NSMakePoint(containerSize.width - NSWidth(button_.bounds),
141 NSMaxY(message_.frame) + kMessageButtonSpacing); 173 NSMaxY(message_.frame) + kMessageButtonSpacing);
142 174
143 containerSize.height = NSMaxY(button_.frame); 175 containerSize.height = NSMaxY(button_.frame);
144 container_.frameSize = containerSize; 176 container_.frameSize = containerSize;
145 177
146 // Center. Top margin is must be between kTabMargin and kMaxTopMargin. 178 // Center. Top margin is must be between kTabMargin and kMaxTopMargin.
147 container_.frameOrigin = NSMakePoint( 179 container_.frameOrigin = NSMakePoint(
148 floor((size.width - containerSize.width) / 2), 180 floor((size.width - containerSize.width) / 2),
149 std::min(kMaxTopMargin, 181 std::min(kMaxTopMargin,
150 std::max(kTabMargin, 182 std::max(kTabMargin,
151 size.height - containerSize.height - kTabMargin))); 183 size.height - containerSize.height - kTabMargin)));
152 } 184 }
153 185
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 { 186 - (void)buttonClicked {
184 [delegate_ sadTabViewButtonClicked:self]; 187 sadTab_->PerformAction(chrome::SadTab::Action::BUTTON);
185 } 188 }
186 189
187 // Called when someone clicks on the embedded link. 190 // Called when someone clicks on the embedded link.
188 - (BOOL)textView:(NSTextView*)textView 191 - (BOOL)textView:(NSTextView*)textView
189 clickedOnLink:(id)link 192 clickedOnLink:(id)link
190 atIndex:(NSUInteger)charIndex { 193 atIndex:(NSUInteger)charIndex {
191 [delegate_ sadTabView:self helpLinkClickedWithURL:(NSString*)link]; 194 sadTab_->PerformAction(chrome::SadTab::Action::HELP_LINK);
192 return YES; 195 return YES;
193 } 196 }
194 197
198 - (NSRange)textView:(NSTextView*)textView
199 willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange
200 toCharacterRange:(NSRange)newSelectedCharRange {
201 return NSMakeRange(0, 0);
202 }
203
195 @end 204 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698