OLD | NEW |
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 #import <Cocoa/Cocoa.h> | 5 #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h" |
6 | 6 |
7 #include "base/logging.h" // for NOTREACHED() | 7 #include "base/logging.h" |
8 #include "base/mac/bundle_locations.h" | 8 #include "base/mac/bundle_locations.h" |
9 #include "base/mac/mac_util.h" | 9 #include "base/mac/mac_util.h" |
10 #include "base/sys_string_conversions.h" | |
11 #include "grit/ui_resources.h" | 10 #include "grit/ui_resources.h" |
12 #include "chrome/browser/api/infobars/confirm_infobar_delegate.h" | |
13 #include "chrome/browser/api/infobars/infobar_service.h" | 11 #include "chrome/browser/api/infobars/infobar_service.h" |
14 #include "chrome/browser/infobars/alternate_nav_infobar_delegate.h" | |
15 #import "chrome/browser/ui/cocoa/animatable_view.h" | 12 #import "chrome/browser/ui/cocoa/animatable_view.h" |
16 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 13 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
17 #include "chrome/browser/ui/cocoa/event_utils.h" | |
18 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" | 14 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" |
19 #import "chrome/browser/ui/cocoa/image_button_cell.h" | 15 #import "chrome/browser/ui/cocoa/image_button_cell.h" |
20 #include "chrome/browser/ui/cocoa/infobars/infobar.h" | 16 #include "chrome/browser/ui/cocoa/infobars/infobar.h" |
21 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" | 17 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h" |
22 #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h" | |
23 #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h" | 18 #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h" |
24 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" | 19 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" |
25 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" | |
26 #include "ui/gfx/image/image.h" | 20 #include "ui/gfx/image/image.h" |
27 #include "webkit/glue/window_open_disposition.h" | |
28 | 21 |
29 namespace { | 22 namespace { |
30 // Durations set to match the default SlideAnimation duration. | 23 // Durations set to match the default SlideAnimation duration. |
31 const float kAnimateOpenDuration = 0.12; | 24 const float kAnimateOpenDuration = 0.12; |
32 const float kAnimateCloseDuration = 0.12; | 25 const float kAnimateCloseDuration = 0.12; |
33 } | 26 } |
34 | 27 |
35 @interface InfoBarController (PrivateMethods) | 28 @interface InfoBarController (PrivateMethods) |
36 // Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil. | 29 // Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil. |
37 - (void)initializeLabel; | 30 - (void)initializeLabel; |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 if (!windowController) { | 270 if (!windowController) { |
278 // This should only happen in unit tests. | 271 // This should only happen in unit tests. |
279 return NSZeroPoint; | 272 return NSZeroPoint; |
280 } | 273 } |
281 | 274 |
282 LocationBarViewMac* locationBar = [windowController locationBarBridge]; | 275 LocationBarViewMac* locationBar = [windowController locationBarBridge]; |
283 return locationBar->GetPageInfoBubblePoint(); | 276 return locationBar->GetPageInfoBubblePoint(); |
284 } | 277 } |
285 | 278 |
286 @end | 279 @end |
287 | |
288 | |
289 ///////////////////////////////////////////////////////////////////////// | |
290 // AlternateNavInfoBarController implementation | |
291 | |
292 @implementation AlternateNavInfoBarController | |
293 | |
294 // Link infobars have a text message, of which part is linkified. We | |
295 // use an NSAttributedString to display styled text, and we set a | |
296 // NSLink attribute on the hyperlink portion of the message. Infobars | |
297 // use a custom NSTextField subclass, which allows us to override | |
298 // textView:clickedOnLink:atIndex: and intercept clicks. | |
299 // | |
300 - (void)addAdditionalControls { | |
301 // No buttons. | |
302 [self removeButtons]; | |
303 | |
304 AlternateNavInfoBarDelegate* delegate = | |
305 delegate_->AsAlternateNavInfoBarDelegate(); | |
306 DCHECK(delegate); | |
307 size_t offset = string16::npos; | |
308 string16 message = delegate->GetMessageTextWithOffset(&offset); | |
309 string16 link = delegate->GetLinkText(); | |
310 NSFont* font = [NSFont labelFontOfSize: | |
311 [NSFont systemFontSizeForControlSize:NSRegularControlSize]]; | |
312 HyperlinkTextView* view = (HyperlinkTextView*)label_.get(); | |
313 [view setMessageAndLink:base::SysUTF16ToNSString(message) | |
314 withLink:base::SysUTF16ToNSString(link) | |
315 atOffset:offset | |
316 font:font | |
317 messageColor:[NSColor blackColor] | |
318 linkColor:[NSColor blueColor]]; | |
319 } | |
320 | |
321 // Called when someone clicks on the link in the infobar. This method | |
322 // is called by the InfobarTextField on its delegate (the | |
323 // AlternateNavInfoBarController). | |
324 - (void)linkClicked { | |
325 if (![self isOwned]) | |
326 return; | |
327 WindowOpenDisposition disposition = | |
328 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); | |
329 if (delegate_->AsAlternateNavInfoBarDelegate()->LinkClicked(disposition)) | |
330 [self removeSelf]; | |
331 } | |
332 | |
333 @end | |
334 | |
335 | |
336 ///////////////////////////////////////////////////////////////////////// | |
337 // ConfirmInfoBarController implementation | |
338 | |
339 @implementation ConfirmInfoBarController | |
340 | |
341 // Called when someone clicks on the "OK" button. | |
342 - (IBAction)ok:(id)sender { | |
343 if (![self isOwned]) | |
344 return; | |
345 if (delegate_->AsConfirmInfoBarDelegate()->Accept()) | |
346 [self removeSelf]; | |
347 } | |
348 | |
349 // Called when someone clicks on the "Cancel" button. | |
350 - (IBAction)cancel:(id)sender { | |
351 if (![self isOwned]) | |
352 return; | |
353 if (delegate_->AsConfirmInfoBarDelegate()->Cancel()) | |
354 [self removeSelf]; | |
355 } | |
356 | |
357 // Confirm infobars can have OK and/or cancel buttons, depending on | |
358 // the return value of GetButtons(). We create each button if | |
359 // required and position them to the left of the close button. | |
360 - (void)addAdditionalControls { | |
361 ConfirmInfoBarDelegate* delegate = delegate_->AsConfirmInfoBarDelegate(); | |
362 DCHECK(delegate); | |
363 int visibleButtons = delegate->GetButtons(); | |
364 | |
365 NSRect okButtonFrame = [okButton_ frame]; | |
366 NSRect cancelButtonFrame = [cancelButton_ frame]; | |
367 | |
368 DCHECK(NSMaxX(cancelButtonFrame) < NSMinX(okButtonFrame)) | |
369 << "Ok button expected to be on the right of the Cancel button in nib"; | |
370 | |
371 CGFloat rightEdge = NSMaxX(okButtonFrame); | |
372 CGFloat spaceBetweenButtons = | |
373 NSMinX(okButtonFrame) - NSMaxX(cancelButtonFrame); | |
374 CGFloat spaceBeforeButtons = | |
375 NSMinX(cancelButtonFrame) - NSMaxX([label_.get() frame]); | |
376 | |
377 // Update and position the OK button if needed. Otherwise, hide it. | |
378 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) { | |
379 [okButton_ setTitle:base::SysUTF16ToNSString( | |
380 delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))]; | |
381 [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_]; | |
382 okButtonFrame = [okButton_ frame]; | |
383 | |
384 // Position the ok button to the left of the Close button. | |
385 okButtonFrame.origin.x = rightEdge - okButtonFrame.size.width; | |
386 [okButton_ setFrame:okButtonFrame]; | |
387 | |
388 // Update the rightEdge | |
389 rightEdge = NSMinX(okButtonFrame); | |
390 } else { | |
391 [okButton_ removeFromSuperview]; | |
392 okButton_ = nil; | |
393 } | |
394 | |
395 // Update and position the Cancel button if needed. Otherwise, hide it. | |
396 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) { | |
397 [cancelButton_ setTitle:base::SysUTF16ToNSString( | |
398 delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))]; | |
399 [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_]; | |
400 cancelButtonFrame = [cancelButton_ frame]; | |
401 | |
402 // If we had a Ok button, leave space between the buttons. | |
403 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) { | |
404 rightEdge -= spaceBetweenButtons; | |
405 } | |
406 | |
407 // Position the Cancel button on our current right edge. | |
408 cancelButtonFrame.origin.x = rightEdge - cancelButtonFrame.size.width; | |
409 [cancelButton_ setFrame:cancelButtonFrame]; | |
410 | |
411 // Update the rightEdge. | |
412 rightEdge = NSMinX(cancelButtonFrame); | |
413 } else { | |
414 [cancelButton_ removeFromSuperview]; | |
415 cancelButton_ = nil; | |
416 } | |
417 | |
418 // If we had either button, leave space before the edge of the textfield. | |
419 if ((visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) || | |
420 (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK)) { | |
421 rightEdge -= spaceBeforeButtons; | |
422 } | |
423 | |
424 NSRect frame = [label_.get() frame]; | |
425 DCHECK(rightEdge > NSMinX(frame)) | |
426 << "Need to make the xib larger to handle buttons with text this long"; | |
427 frame.size.width = rightEdge - NSMinX(frame); | |
428 [label_.get() setFrame:frame]; | |
429 | |
430 // Set the text and link. | |
431 NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText()); | |
432 string16 link = delegate->GetLinkText(); | |
433 if (!link.empty()) { | |
434 // Add spacing between the label and the link. | |
435 message = [message stringByAppendingString:@" "]; | |
436 } | |
437 NSFont* font = [NSFont labelFontOfSize: | |
438 [NSFont systemFontSizeForControlSize:NSRegularControlSize]]; | |
439 HyperlinkTextView* view = (HyperlinkTextView*)label_.get(); | |
440 [view setMessageAndLink:message | |
441 withLink:base::SysUTF16ToNSString(link) | |
442 atOffset:[message length] | |
443 font:font | |
444 messageColor:[NSColor blackColor] | |
445 linkColor:[NSColor blueColor]]; | |
446 } | |
447 | |
448 // Called when someone clicks on the link in the infobar. This method | |
449 // is called by the InfobarTextField on its delegate (the | |
450 // AlternateNavInfoBarController). | |
451 - (void)linkClicked { | |
452 if (![self isOwned]) | |
453 return; | |
454 WindowOpenDisposition disposition = | |
455 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); | |
456 if (delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition)) | |
457 [self removeSelf]; | |
458 } | |
459 | |
460 @end | |
461 | |
462 | |
463 ////////////////////////////////////////////////////////////////////////// | |
464 // CreateInfoBar() implementations | |
465 | |
466 InfoBar* AlternateNavInfoBarDelegate::CreateInfoBar(InfoBarService* owner) { | |
467 AlternateNavInfoBarController* controller = | |
468 [[AlternateNavInfoBarController alloc] initWithDelegate:this owner:owner]; | |
469 return new InfoBar(controller, this); | |
470 } | |
471 | |
472 InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) { | |
473 ConfirmInfoBarController* controller = | |
474 [[ConfirmInfoBarController alloc] initWithDelegate:this owner:owner]; | |
475 return new InfoBar(controller, this); | |
476 } | |
OLD | NEW |