| 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 |