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

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

Powered by Google App Engine
This is Rietveld 408576698