1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/cocoa/infobars/confirm_infobar_controller.h" 6 7 #include "base/logging.h" 8 #include "base/strings/sys_string_conversions.h" 9 #include "chrome/browser/infobars/confirm_infobar_delegate.h" 10 #import "chrome/browser/ui/cocoa/hyperlink_text_view.h" 11 #include "chrome/browser/ui/cocoa/infobars/infobar.h" 12 #include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" 13 #import "ui/base/cocoa/cocoa_event_utils.h" 14 #include "ui/base/window_open_disposition.h" 15 16 @implementation ConfirmInfoBarController 17 18 // Called when someone clicks on the "OK" button. 19 - (IBAction)ok:(id)sender { 20 if (![self isOwned]) 21 return; 22 if (delegate_->AsConfirmInfoBarDelegate()->Accept()) 23 [self removeSelf]; 24 } 25 26 // Called when someone clicks on the "Cancel" button. 27 - (IBAction)cancel:(id)sender { 28 if (![self isOwned]) 29 return; 30 if (delegate_->AsConfirmInfoBarDelegate()->Cancel()) 31 [self removeSelf]; 32 } 33 34 // Confirm infobars can have OK and/or cancel buttons, depending on 35 // the return value of GetButtons(). We create each button if 36 // required and position them to the left of the close button. 37 - (void)addAdditionalControls { 38 ConfirmInfoBarDelegate* delegate = delegate_->AsConfirmInfoBarDelegate(); 39 DCHECK(delegate); 40 int visibleButtons = delegate->GetButtons(); 41 42 NSRect okButtonFrame = [okButton_ frame]; 43 NSRect cancelButtonFrame = [cancelButton_ frame]; 44 45 DCHECK(NSMaxX(cancelButtonFrame) < NSMinX(okButtonFrame)) 46 << "Ok button expected to be on the right of the Cancel button in nib"; 47 48 CGFloat rightEdge = NSMaxX(okButtonFrame); 49 CGFloat spaceBetweenButtons = 50 NSMinX(okButtonFrame) - NSMaxX(cancelButtonFrame); 51 CGFloat spaceBeforeButtons = 52 NSMinX(cancelButtonFrame) - NSMaxX([label_.get() frame]); 53 54 // Update and position the OK button if needed. Otherwise, hide it. 55 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) { 56 [okButton_ setTitle:base::SysUTF16ToNSString( 57 delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))]; 58 [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_]; 59 okButtonFrame = [okButton_ frame]; 60 61 // Position the ok button to the left of the Close button. 62 okButtonFrame.origin.x = rightEdge - okButtonFrame.size.width; 63 [okButton_ setFrame:okButtonFrame]; 64 65 // Update the rightEdge 66 rightEdge = NSMinX(okButtonFrame); 67 } else { 68 [okButton_ removeFromSuperview]; 69 okButton_ = nil; 70 } 71 72 // Update and position the Cancel button if needed. Otherwise, hide it. 73 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) { 74 [cancelButton_ setTitle:base::SysUTF16ToNSString( 75 delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))]; 76 [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_]; 77 cancelButtonFrame = [cancelButton_ frame]; 78 79 // If we had a Ok button, leave space between the buttons. 80 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) { 81 rightEdge -= spaceBetweenButtons; 82 } 83 84 // Position the Cancel button on our current right edge. 85 cancelButtonFrame.origin.x = rightEdge - cancelButtonFrame.size.width; 86 [cancelButton_ setFrame:cancelButtonFrame]; 87 88 // Update the rightEdge. 89 rightEdge = NSMinX(cancelButtonFrame); 90 } else { 91 [cancelButton_ removeFromSuperview]; 92 cancelButton_ = nil; 93 } 94 95 // If we had either button, leave space before the edge of the textfield. 96 if ((visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) || 97 (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK)) { 98 rightEdge -= spaceBeforeButtons; 99 } 100 101 NSRect frame = [label_.get() frame]; 102 DCHECK(rightEdge > NSMinX(frame)) 103 << "Need to make the xib larger to handle buttons with text this long"; 104 frame.size.width = rightEdge - NSMinX(frame); 105 [label_.get() setFrame:frame]; 106 107 // Set the text and link. 108 NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText()); 109 string16 link = delegate->GetLinkText(); 110 if (!link.empty()) { 111 // Add spacing between the label and the link. 112 message = [message stringByAppendingString:@" "]; 113 } 114 NSFont* font = [NSFont labelFontOfSize: 115 [NSFont systemFontSizeForControlSize:NSRegularControlSize]]; 116 HyperlinkTextView* view = (HyperlinkTextView*)label_.get(); 117 [view setMessageAndLink:message 118 withLink:base::SysUTF16ToNSString(link) 119 atOffset:[message length] 120 font:font 121 messageColor:[NSColor blackColor] 122 linkColor:[NSColor blueColor]]; 123 } 124 125 // Called when someone clicks on the link in the infobar. This method 126 // is called by the InfobarTextField on its delegate (the 127 // AlternateNavInfoBarController). 128 - (void)linkClicked { 129 if (![self isOwned]) 130 return; 131 WindowOpenDisposition disposition = 132 ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); 133 if (delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition)) 134 [self removeSelf]; 135 } 136 137 @end 138 139 InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) { 140 ConfirmInfoBarController* controller = 141 [[ConfirmInfoBarController alloc] initWithDelegate:this owner:owner]; 142 return new InfoBar(controller, this); 143 } 144