Home | History | Annotate | Download | only in infobars
      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
      3 // found in the LICENSE file.
      4 
      5 #import "chrome/browser/ui/cocoa/infobars/infobar_controller.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/mac/bundle_locations.h"
      9 #include "base/mac/mac_util.h"
     10 #include "chrome/browser/infobars/infobar_service.h"
     11 #import "chrome/browser/ui/cocoa/animatable_view.h"
     12 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
     13 #import "chrome/browser/ui/cocoa/image_button_cell.h"
     14 #include "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
     15 #import "chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h"
     16 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
     17 #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
     18 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
     19 #include "grit/theme_resources.h"
     20 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
     21 #include "ui/gfx/image/image.h"
     22 #include "ui/resources/grit/ui_resources.h"
     23 
     24 @interface InfoBarController ()
     25 // Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil.
     26 - (void)initializeLabel;
     27 @end
     28 
     29 @implementation InfoBarController
     30 
     31 @synthesize containerController = containerController_;
     32 
     33 - (id)initWithInfoBar:(InfoBarCocoa*)infobar {
     34   if ((self = [super initWithNibName:@"InfoBar"
     35                               bundle:base::mac::FrameworkBundle()])) {
     36     DCHECK(infobar);
     37     infobar_ = infobar->GetWeakPtr();
     38   }
     39   return self;
     40 }
     41 
     42 // All infobars have an icon, so we set up the icon in the base class
     43 // awakeFromNib.
     44 - (void)awakeFromNib {
     45   [[closeButton_ cell] setImageID:IDR_CLOSE_1
     46                    forButtonState:image_button_cell::kDefaultState];
     47   [[closeButton_ cell] setImageID:IDR_CLOSE_1_H
     48                    forButtonState:image_button_cell::kHoverState];
     49   [[closeButton_ cell] setImageID:IDR_CLOSE_1_P
     50                    forButtonState:image_button_cell::kPressedState];
     51   [[closeButton_ cell] setImageID:IDR_CLOSE_1
     52                    forButtonState:image_button_cell::kDisabledState];
     53 
     54   if (![self delegate]->GetIcon().IsEmpty()) {
     55     [image_ setImage:[self delegate]->GetIcon().ToNSImage()];
     56   } else {
     57     // No icon, remove it from the view and grow the textfield to include the
     58     // space.
     59     NSRect imageFrame = [image_ frame];
     60     NSRect labelFrame = [labelPlaceholder_ frame];
     61     labelFrame.size.width += NSMinX(imageFrame) - NSMinX(labelFrame);
     62     labelFrame.origin.x = imageFrame.origin.x;
     63     [image_ removeFromSuperview];
     64     image_ = nil;
     65     [labelPlaceholder_ setFrame:labelFrame];
     66   }
     67   [self initializeLabel];
     68 
     69   [self addAdditionalControls];
     70 
     71   [infoBarView_ setInfobarType:[self delegate]->GetInfoBarType()];
     72   [infoBarView_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
     73 }
     74 
     75 - (void)dealloc {
     76   [okButton_ setTarget:nil];
     77   [cancelButton_ setTarget:nil];
     78   [closeButton_ setTarget:nil];
     79   [super dealloc];
     80 }
     81 
     82 - (InfoBarCocoa*)infobar {
     83   return infobar_.get();
     84 }
     85 
     86 // Called when someone clicks on the embedded link.
     87 - (BOOL)textView:(NSTextView*)textView
     88    clickedOnLink:(id)link
     89          atIndex:(NSUInteger)charIndex {
     90   if ([self respondsToSelector:@selector(linkClicked)])
     91     [self performSelector:@selector(linkClicked)];
     92   return YES;
     93 }
     94 
     95 - (BOOL)isOwned {
     96   return infobar_ && infobar_->OwnerCocoa() != NULL;
     97 }
     98 
     99 // Called when someone clicks on the ok button.
    100 - (void)ok:(id)sender {
    101   // Subclasses must override this method if they do not hide the ok button.
    102   NOTREACHED();
    103 }
    104 
    105 // Called when someone clicks on the cancel button.
    106 - (void)cancel:(id)sender {
    107   // Subclasses must override this method if they do not hide the cancel button.
    108   NOTREACHED();
    109 }
    110 
    111 // Called when someone clicks on the close button.
    112 - (void)dismiss:(id)sender {
    113   if (![self isOwned])
    114     return;
    115   [self delegate]->InfoBarDismissed();
    116   [self removeSelf];
    117 }
    118 
    119 - (void)removeSelf {
    120   infobar_->RemoveSelf();
    121 }
    122 
    123 - (void)addAdditionalControls {
    124   // Default implementation does nothing.
    125 }
    126 
    127 - (void)infobarWillHide {
    128 }
    129 
    130 - (void)infobarWillClose {
    131 }
    132 
    133 - (void)removeButtons {
    134   // Extend the label all the way across.
    135   NSRect labelFrame = [label_.get() frame];
    136   labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame);
    137   [okButton_ removeFromSuperview];
    138   okButton_ = nil;
    139   [cancelButton_ removeFromSuperview];
    140   cancelButton_ = nil;
    141   [label_.get() setFrame:labelFrame];
    142 }
    143 
    144 - (void)layoutArrow {
    145   [infoBarView_ setArrowHeight:infobar_->arrow_height()];
    146   [infoBarView_ setArrowHalfWidth:infobar_->arrow_half_width()];
    147   [infoBarView_ setHasTip:![containerController_ shouldSuppressTopInfoBarTip]];
    148 
    149   // Convert from window to view coordinates.
    150   NSPoint point = NSMakePoint([containerController_ infobarArrowX], 0);
    151   point = [infoBarView_ convertPoint:point fromView:nil];
    152   [infoBarView_ setArrowX:point.x];
    153 }
    154 
    155 - (void)disablePopUpMenu:(NSMenu*)menu {
    156   // If the menu is re-opened, prevent queries to update items.
    157   [menu setDelegate:nil];
    158 
    159   // Prevent target/action messages to the controller.
    160   for (NSMenuItem* item in [menu itemArray]) {
    161     [item setEnabled:NO];
    162     [item setTarget:nil];
    163   }
    164 }
    165 
    166 - (infobars::InfoBarDelegate*)delegate {
    167   return infobar_->delegate();
    168 }
    169 
    170 - (void)initializeLabel {
    171   // Replace the label placeholder NSTextField with the real label NSTextView.
    172   // The former doesn't show links in a nice way, but the latter can't be added
    173   // in IB without a containing scroll view, so create the NSTextView
    174   // programmatically.
    175   base::scoped_nsobject<HyperlinkTextView> newLabel(
    176     [[HyperlinkTextView alloc] initWithFrame:[labelPlaceholder_ frame]]);
    177   [newLabel setDrawsBackgroundUsingSuperview:YES];
    178   [newLabel setAutoresizingMask:[labelPlaceholder_ autoresizingMask]];
    179   [[labelPlaceholder_ superview]
    180       replaceSubview:labelPlaceholder_ with:newLabel];
    181   labelPlaceholder_ = nil;  // Now released.
    182   [newLabel setDelegate:self];
    183 
    184   label_.reset(newLabel.release());
    185 }
    186 
    187 @end
    188