Home | History | Annotate | Download | only in infobars
      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