infobar_controller.mm revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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/hyperlink_text_view.h"
14#import "chrome/browser/ui/cocoa/image_button_cell.h"
15#include "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
16#import "chrome/browser/ui/cocoa/infobars/infobar_container_cocoa.h"
17#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
18#import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
19#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
20#include "grit/theme_resources.h"
21#include "grit/ui_resources.h"
22#include "ui/gfx/image/image.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}
73
74- (void)dealloc {
75  [okButton_ setTarget:nil];
76  [cancelButton_ setTarget:nil];
77  [closeButton_ setTarget:nil];
78  [super dealloc];
79}
80
81- (InfoBarCocoa*)infobar {
82  return infobar_.get();
83}
84
85// Called when someone clicks on the embedded link.
86- (BOOL)textView:(NSTextView*)textView
87   clickedOnLink:(id)link
88         atIndex:(NSUInteger)charIndex {
89  if ([self respondsToSelector:@selector(linkClicked)])
90    [self performSelector:@selector(linkClicked)];
91  return YES;
92}
93
94- (BOOL)isOwned {
95  return infobar_ && infobar_->OwnerCocoa() != NULL;
96}
97
98// Called when someone clicks on the ok button.
99- (void)ok:(id)sender {
100  // Subclasses must override this method if they do not hide the ok button.
101  NOTREACHED();
102}
103
104// Called when someone clicks on the cancel button.
105- (void)cancel:(id)sender {
106  // Subclasses must override this method if they do not hide the cancel button.
107  NOTREACHED();
108}
109
110// Called when someone clicks on the close button.
111- (void)dismiss:(id)sender {
112  if (![self isOwned])
113    return;
114  [self delegate]->InfoBarDismissed();
115  [self removeSelf];
116}
117
118- (void)removeSelf {
119  infobar_->RemoveSelf();
120}
121
122- (void)addAdditionalControls {
123  // Default implementation does nothing.
124}
125
126- (void)infobarWillHide {
127}
128
129- (void)infobarWillClose {
130}
131
132- (void)removeButtons {
133  // Extend the label all the way across.
134  NSRect labelFrame = [label_.get() frame];
135  labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame);
136  [okButton_ removeFromSuperview];
137  okButton_ = nil;
138  [cancelButton_ removeFromSuperview];
139  cancelButton_ = nil;
140  [label_.get() setFrame:labelFrame];
141}
142
143- (void)layoutArrow {
144  [infoBarView_ setArrowHeight:infobar_->arrow_height()];
145  [infoBarView_ setArrowHalfWidth:infobar_->arrow_half_width()];
146  [infoBarView_ setHasTip:![containerController_ shouldSuppressTopInfoBarTip]];
147
148  // Convert from window to view coordinates.
149  NSPoint point = NSMakePoint([containerController_ infobarArrowX], 0);
150  point = [infoBarView_ convertPoint:point fromView:nil];
151  [infoBarView_ setArrowX:point.x];
152}
153
154- (void)disablePopUpMenu:(NSMenu*)menu {
155  // If the menu is re-opened, prevent queries to update items.
156  [menu setDelegate:nil];
157
158  // Prevent target/action messages to the controller.
159  for (NSMenuItem* item in [menu itemArray]) {
160    [item setEnabled:NO];
161    [item setTarget:nil];
162  }
163}
164
165- (infobars::InfoBarDelegate*)delegate {
166  return infobar_->delegate();
167}
168
169- (void)initializeLabel {
170  // Replace the label placeholder NSTextField with the real label NSTextView.
171  // The former doesn't show links in a nice way, but the latter can't be added
172  // in IB without a containing scroll view, so create the NSTextView
173  // programmatically.
174  base::scoped_nsobject<HyperlinkTextView> newLabel(
175    [[HyperlinkTextView alloc] initWithFrame:[labelPlaceholder_ frame]]);
176  [newLabel setDrawsBackgroundUsingSuperview:YES];
177  [newLabel setAutoresizingMask:[labelPlaceholder_ autoresizingMask]];
178  [[labelPlaceholder_ superview]
179      replaceSubview:labelPlaceholder_ with:newLabel];
180  labelPlaceholder_ = nil;  // Now released.
181  [newLabel setDelegate:self];
182
183  label_.reset(newLabel.release());
184}
185
186@end
187