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

Side by Side Diff: chrome/browser/ui/cocoa/infobars/infobar_controller.mm

Issue 7610011: Update Sad Tab help text and link. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync and merge. Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #import <Cocoa/Cocoa.h> 5 #import <Cocoa/Cocoa.h>
6 6
7 #include "base/logging.h" // for NOTREACHED() 7 #include "base/logging.h" // for NOTREACHED()
8 #include "base/mac/mac_util.h" 8 #include "base/mac/mac_util.h"
9 #include "base/sys_string_conversions.h" 9 #include "base/sys_string_conversions.h"
10 #include "chrome/browser/infobars/infobar_tab_helper.h" 10 #include "chrome/browser/infobars/infobar_tab_helper.h"
11 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" 11 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
12 #include "chrome/browser/tab_contents/link_infobar_delegate.h" 12 #include "chrome/browser/tab_contents/link_infobar_delegate.h"
13 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
14 #import "chrome/browser/ui/cocoa/animatable_view.h" 13 #import "chrome/browser/ui/cocoa/animatable_view.h"
15 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 14 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
16 #include "chrome/browser/ui/cocoa/event_utils.h" 15 #include "chrome/browser/ui/cocoa/event_utils.h"
16 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
17 #include "chrome/browser/ui/cocoa/infobars/infobar.h" 17 #include "chrome/browser/ui/cocoa/infobars/infobar.h"
18 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" 18 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
19 #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h" 19 #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
20 #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h" 20 #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
21 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" 21 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
22 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
22 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" 23 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
23 #include "ui/gfx/image/image.h" 24 #include "ui/gfx/image/image.h"
24 #include "webkit/glue/window_open_disposition.h" 25 #include "webkit/glue/window_open_disposition.h"
25 26
26 namespace { 27 namespace {
27 // Durations set to match the default SlideAnimation duration. 28 // Durations set to match the default SlideAnimation duration.
28 const float kAnimateOpenDuration = 0.12; 29 const float kAnimateOpenDuration = 0.12;
29 const float kAnimateCloseDuration = 0.12; 30 const float kAnimateCloseDuration = 0.12;
30
31 // The baseline shift for text in the NSTextView.
32 const float kTextBaselineShift = -1.0;
33 } 31 }
34 32
35 // This simple subclass of |NSTextView| just doesn't show the (text) cursor
36 // (|NSTextView| displays the cursor with full keyboard accessibility enabled).
37 @interface InfoBarTextView : NSTextView
38 - (void)fixupCursor;
39 @end
40
41 @implementation InfoBarTextView
42
43 // Never draw the insertion point (otherwise, it shows up without any user
44 // action if full keyboard accessibility is enabled).
45 - (BOOL)shouldDrawInsertionPoint {
46 return NO;
47 }
48
49 - (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange
50 granularity:(NSSelectionGranularity)granularity {
51 // Do not allow selections.
52 return NSMakeRange(0, 0);
53 }
54
55 // Convince NSTextView to not show an I-Beam cursor when the cursor is over the
56 // text view but not over actual text.
57 //
58 // http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10791.html
59 // "NSTextView sets the cursor over itself dynamically, based on considerations
60 // including the text under the cursor. It does so in -mouseEntered:,
61 // -mouseMoved:, and -cursorUpdate:, so those would be points to consider
62 // overriding."
63 - (void)mouseMoved:(NSEvent*)e {
64 [super mouseMoved:e];
65 [self fixupCursor];
66 }
67
68 - (void)mouseEntered:(NSEvent*)e {
69 [super mouseEntered:e];
70 [self fixupCursor];
71 }
72
73 - (void)cursorUpdate:(NSEvent*)e {
74 [super cursorUpdate:e];
75 [self fixupCursor];
76 }
77
78 - (void)fixupCursor {
79 if ([[NSCursor currentCursor] isEqual:[NSCursor IBeamCursor]])
80 [[NSCursor arrowCursor] set];
81 }
82
83 @end
84
85 @interface InfoBarController (PrivateMethods) 33 @interface InfoBarController (PrivateMethods)
86 // Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil. 34 // Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil.
87 - (void)initializeLabel; 35 - (void)initializeLabel;
88 36
89 // Asks the container controller to remove the infobar for this delegate. This 37 // Asks the container controller to remove the infobar for this delegate. This
90 // call will trigger a notification that starts the infobar animating closed. 38 // call will trigger a notification that starts the infobar animating closed.
91 - (void)removeSelf; 39 - (void)removeSelf;
92 40
93 // Performs final cleanup after an animation is finished or stopped, including 41 // Performs final cleanup after an animation is finished or stopped, including
94 // notifying the InfoBarDelegate that the infobar was closed and removing the 42 // notifying the InfoBarDelegate that the infobar was closed and removing the
95 // infobar from its container, if necessary. 43 // infobar from its container, if necessary.
96 - (void)cleanUpAfterAnimation:(BOOL)finished; 44 - (void)cleanUpAfterAnimation:(BOOL)finished;
97 45
98 // Sets the info bar message to the specified |message|, with a hypertext
99 // style link. |link| will be inserted into message at |linkOffset|.
100 - (void)setLabelToMessage:(NSString*)message
101 withLink:(NSString*)link
102 atOffset:(NSUInteger)linkOffset;
103
104 // Returns the point, in gradient view coordinates, at which the apex of the 46 // Returns the point, in gradient view coordinates, at which the apex of the
105 // infobar tip should be drawn. 47 // infobar tip should be drawn.
106 - (NSPoint)pointForTipApex; 48 - (NSPoint)pointForTipApex;
107 @end 49 @end
108 50
109 @implementation InfoBarController 51 @implementation InfoBarController
110 52
111 @synthesize containerController = containerController_; 53 @synthesize containerController = containerController_;
112 @synthesize delegate = delegate_; 54 @synthesize delegate = delegate_;
113 55
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 } 164 }
223 165
224 - (void)addAdditionalControls { 166 - (void)addAdditionalControls {
225 // Default implementation does nothing. 167 // Default implementation does nothing.
226 } 168 }
227 169
228 - (void)infobarWillClose { 170 - (void)infobarWillClose {
229 // Default implementation does nothing. 171 // Default implementation does nothing.
230 } 172 }
231 173
232 - (void)setLabelToMessage:(NSString*)message {
233 NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
234 NSFont* font = [NSFont labelFontOfSize:
235 [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
236 [attributes setObject:font
237 forKey:NSFontAttributeName];
238 [attributes setObject:[NSCursor arrowCursor]
239 forKey:NSCursorAttributeName];
240 [attributes setObject:[NSNumber numberWithFloat:kTextBaselineShift]
241 forKey:NSBaselineOffsetAttributeName];
242 scoped_nsobject<NSAttributedString> attributedString(
243 [[NSAttributedString alloc] initWithString:message
244 attributes:attributes]);
245 [[label_.get() textStorage] setAttributedString:attributedString];
246 }
247
248 - (void)removeButtons { 174 - (void)removeButtons {
249 // Extend the label all the way across. 175 // Extend the label all the way across.
250 NSRect labelFrame = [label_.get() frame]; 176 NSRect labelFrame = [label_.get() frame];
251 labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame); 177 labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame);
252 [okButton_ removeFromSuperview]; 178 [okButton_ removeFromSuperview];
253 [cancelButton_ removeFromSuperview]; 179 [cancelButton_ removeFromSuperview];
254 [label_.get() setFrame:labelFrame]; 180 [label_.get() setFrame:labelFrame];
255 } 181 }
256 182
257 @end 183 @end
258 184
259 @implementation InfoBarController (PrivateMethods) 185 @implementation InfoBarController (PrivateMethods)
260 186
261 - (void)initializeLabel { 187 - (void)initializeLabel {
262 // Replace the label placeholder NSTextField with the real label NSTextView. 188 // Replace the label placeholder NSTextField with the real label NSTextView.
263 // The former doesn't show links in a nice way, but the latter can't be added 189 // The former doesn't show links in a nice way, but the latter can't be added
264 // in IB without a containing scroll view, so create the NSTextView 190 // in IB without a containing scroll view, so create the NSTextView
265 // programmatically. 191 // programmatically.
266 label_.reset([[InfoBarTextView alloc] 192 label_.reset([[HyperlinkTextView alloc]
267 initWithFrame:[labelPlaceholder_ frame]]); 193 initWithFrame:[labelPlaceholder_ frame]]);
268 [label_.get() setAutoresizingMask:[labelPlaceholder_ autoresizingMask]]; 194 [label_.get() setAutoresizingMask:[labelPlaceholder_ autoresizingMask]];
269 [[labelPlaceholder_ superview] 195 [[labelPlaceholder_ superview]
270 replaceSubview:labelPlaceholder_ with:label_.get()]; 196 replaceSubview:labelPlaceholder_ with:label_.get()];
271 labelPlaceholder_ = nil; // Now released. 197 labelPlaceholder_ = nil; // Now released.
272 [label_.get() setDelegate:self]; 198 [label_.get() setDelegate:self];
273 [label_.get() setEditable:NO];
274 [label_.get() setDrawsBackground:NO];
275 [label_.get() setHorizontallyResizable:NO];
276 [label_.get() setVerticallyResizable:NO];
277 } 199 }
278 200
279 - (void)removeSelf { 201 - (void)removeSelf {
280 // TODO(rohitrao): This method can be called even if the infobar has already 202 // TODO(rohitrao): This method can be called even if the infobar has already
281 // been removed and |delegate_| is NULL. Is there a way to rewrite the code 203 // been removed and |delegate_| is NULL. Is there a way to rewrite the code
282 // so that inner event loops don't cause us to try and remove the infobar 204 // so that inner event loops don't cause us to try and remove the infobar
283 // twice? http://crbug.com/54253 205 // twice? http://crbug.com/54253
284 if (owner_) 206 if (owner_)
285 owner_->infobar_tab_helper()->RemoveInfoBar(delegate_); 207 owner_->infobar_tab_helper()->RemoveInfoBar(delegate_);
286 owner_ = NULL; 208 owner_ = NULL;
(...skipping 20 matching lines...) Expand all
307 } 229 }
308 230
309 - (void)animationDidStop:(NSAnimation*)animation { 231 - (void)animationDidStop:(NSAnimation*)animation {
310 [self cleanUpAfterAnimation:NO]; 232 [self cleanUpAfterAnimation:NO];
311 } 233 }
312 234
313 - (void)animationDidEnd:(NSAnimation*)animation { 235 - (void)animationDidEnd:(NSAnimation*)animation {
314 [self cleanUpAfterAnimation:YES]; 236 [self cleanUpAfterAnimation:YES];
315 } 237 }
316 238
317 // TODO(joth): This method factors out some common functionality between the
318 // various derived infobar classes, however the class hierarchy itself could
319 // use refactoring to reduce this duplication. http://crbug.com/38924
320 - (void)setLabelToMessage:(NSString*)message
321 withLink:(NSString*)link
322 atOffset:(NSUInteger)linkOffset {
323 if (linkOffset == std::wstring::npos) {
324 // linkOffset == std::wstring::npos means the link should be right-aligned,
325 // which is not supported on Mac (http://crbug.com/47728).
326 NOTIMPLEMENTED();
327 linkOffset = [message length];
328 }
329 // Create an attributes dictionary for the entire message. We have
330 // to explicitly set the control's font. We also override the cursor to give
331 // us the normal cursor rather than the text insertion cursor.
332 NSMutableDictionary* linkAttributes = [NSMutableDictionary dictionary];
333 [linkAttributes setObject:[NSCursor arrowCursor]
334 forKey:NSCursorAttributeName];
335 NSFont* font = [NSFont labelFontOfSize:
336 [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
337 [linkAttributes setObject:font
338 forKey:NSFontAttributeName];
339
340 // Create the attributed string for the main message text.
341 scoped_nsobject<NSMutableAttributedString> infoText(
342 [[NSMutableAttributedString alloc] initWithString:message]);
343 [infoText.get() addAttributes:linkAttributes
344 range:NSMakeRange(0, [infoText.get() length])];
345 // Add additional attributes to style the link text appropriately as
346 // well as linkify it.
347 [linkAttributes setObject:[NSColor blueColor]
348 forKey:NSForegroundColorAttributeName];
349 [linkAttributes setObject:[NSNumber numberWithBool:YES]
350 forKey:NSUnderlineStyleAttributeName];
351 [linkAttributes setObject:[NSCursor pointingHandCursor]
352 forKey:NSCursorAttributeName];
353 [linkAttributes setObject:[NSNumber numberWithInt:NSSingleUnderlineStyle]
354 forKey:NSUnderlineStyleAttributeName];
355 [linkAttributes setObject:[NSString string] // dummy value
356 forKey:NSLinkAttributeName];
357
358 // Insert the link text into the string at the appropriate offset.
359 scoped_nsobject<NSAttributedString> attributedString(
360 [[NSAttributedString alloc] initWithString:link
361 attributes:linkAttributes]);
362 [infoText.get() insertAttributedString:attributedString.get()
363 atIndex:linkOffset];
364 // The entire text needs a baseline shift.
365 [infoText addAttribute:NSBaselineOffsetAttributeName
366 value:[NSNumber numberWithDouble:kTextBaselineShift]
367 range:NSMakeRange(0, [infoText length])];
368
369 // Update the label view with the new text.
370 [[label_.get() textStorage] setAttributedString:infoText];
371 }
372
373 - (NSPoint)pointForTipApex { 239 - (NSPoint)pointForTipApex {
374 BrowserWindowController* windowController = 240 BrowserWindowController* windowController =
375 [containerController_ browserWindowController]; 241 [containerController_ browserWindowController];
376 if (!windowController) { 242 if (!windowController) {
377 // This should only happen in unit tests. 243 // This should only happen in unit tests.
378 return NSZeroPoint; 244 return NSZeroPoint;
379 } 245 }
380 246
381 LocationBarViewMac* locationBar = [windowController locationBarBridge]; 247 LocationBarViewMac* locationBar = [windowController locationBarBridge];
382 NSPoint point = locationBar->GetPageInfoBubblePoint(); 248 NSPoint point = locationBar->GetPageInfoBubblePoint();
(...skipping 16 matching lines...) Expand all
399 // textView:clickedOnLink:atIndex: and intercept clicks. 265 // textView:clickedOnLink:atIndex: and intercept clicks.
400 // 266 //
401 - (void)addAdditionalControls { 267 - (void)addAdditionalControls {
402 // No buttons. 268 // No buttons.
403 [self removeButtons]; 269 [self removeButtons];
404 270
405 LinkInfoBarDelegate* delegate = delegate_->AsLinkInfoBarDelegate(); 271 LinkInfoBarDelegate* delegate = delegate_->AsLinkInfoBarDelegate();
406 DCHECK(delegate); 272 DCHECK(delegate);
407 size_t offset = std::wstring::npos; 273 size_t offset = std::wstring::npos;
408 string16 message = delegate->GetMessageTextWithOffset(&offset); 274 string16 message = delegate->GetMessageTextWithOffset(&offset);
409 [self setLabelToMessage:base::SysUTF16ToNSString(message) 275 string16 link = delegate->GetLinkText();
410 withLink:base::SysUTF16ToNSString(delegate->GetLinkText()) 276 NSFont* font = [NSFont labelFontOfSize:
411 atOffset:offset]; 277 [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
278 HyperlinkTextView* view = (HyperlinkTextView*)label_.get();
279 [view setMessageAndLink:base::SysUTF16ToNSString(message)
280 withLink:base::SysUTF16ToNSString(link)
281 atOffset:offset
282 font:font
283 messageColor:[NSColor blackColor]
284 linkColor:[NSColor blueColor]];
412 } 285 }
413 286
414 // Called when someone clicks on the link in the infobar. This method 287 // Called when someone clicks on the link in the infobar. This method
415 // is called by the InfobarTextField on its delegate (the 288 // is called by the InfobarTextField on its delegate (the
416 // LinkInfoBarController). 289 // LinkInfoBarController).
417 - (void)linkClicked { 290 - (void)linkClicked {
418 WindowOpenDisposition disposition = 291 WindowOpenDisposition disposition =
419 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); 292 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
420 if (delegate_ && 293 if (delegate_ &&
421 delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition)) { 294 delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition)) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 391
519 NSRect frame = [label_.get() frame]; 392 NSRect frame = [label_.get() frame];
520 DCHECK(rightEdge > NSMinX(frame)) 393 DCHECK(rightEdge > NSMinX(frame))
521 << "Need to make the xib larger to handle buttons with text this long"; 394 << "Need to make the xib larger to handle buttons with text this long";
522 frame.size.width = rightEdge - NSMinX(frame); 395 frame.size.width = rightEdge - NSMinX(frame);
523 [label_.get() setFrame:frame]; 396 [label_.get() setFrame:frame];
524 397
525 // Set the text and link. 398 // Set the text and link.
526 NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText()); 399 NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText());
527 string16 link = delegate->GetLinkText(); 400 string16 link = delegate->GetLinkText();
528 if (link.empty()) { 401 if (!link.empty()) {
529 // Simple case: no link, so just set the message directly.
530 [self setLabelToMessage:message];
531 } else {
532 // Inserting the link unintentionally causes the text to have a slightly
533 // different result to the simple case above: text is truncated on word
534 // boundaries (if needed) rather than elided with ellipses.
535
536 // Add spacing between the label and the link. 402 // Add spacing between the label and the link.
537 message = [message stringByAppendingString:@" "]; 403 message = [message stringByAppendingString:@" "];
538 [self setLabelToMessage:message
539 withLink:base::SysUTF16ToNSString(link)
540 atOffset:[message length]];
541 } 404 }
405 NSFont* font = [NSFont labelFontOfSize:
406 [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
407 HyperlinkTextView* view = (HyperlinkTextView*)label_.get();
408 [view setMessageAndLink:message
409 withLink:base::SysUTF16ToNSString(link)
410 atOffset:[message length]
411 font:font
412 messageColor:[NSColor blackColor]
413 linkColor:[NSColor blueColor]];
542 } 414 }
543 415
544 // Called when someone clicks on the link in the infobar. This method 416 // Called when someone clicks on the link in the infobar. This method
545 // is called by the InfobarTextField on its delegate (the 417 // is called by the InfobarTextField on its delegate (the
546 // LinkInfoBarController). 418 // LinkInfoBarController).
547 - (void)linkClicked { 419 - (void)linkClicked {
548 WindowOpenDisposition disposition = 420 WindowOpenDisposition disposition =
549 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); 421 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
550 if (delegate_ && 422 if (delegate_ &&
551 delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition)) 423 delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition))
(...skipping 10 matching lines...) Expand all
562 LinkInfoBarController* controller = 434 LinkInfoBarController* controller =
563 [[LinkInfoBarController alloc] initWithDelegate:this owner:owner]; 435 [[LinkInfoBarController alloc] initWithDelegate:this owner:owner];
564 return new InfoBar(controller, this); 436 return new InfoBar(controller, this);
565 } 437 }
566 438
567 InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(TabContentsWrapper* owner) { 439 InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(TabContentsWrapper* owner) {
568 ConfirmInfoBarController* controller = 440 ConfirmInfoBarController* controller =
569 [[ConfirmInfoBarController alloc] initWithDelegate:this owner:owner]; 441 [[ConfirmInfoBarController alloc] initWithDelegate:this owner:owner];
570 return new InfoBar(controller, this); 442 return new InfoBar(controller, this);
571 } 443 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/infobars/infobar_controller.h ('k') | chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698