Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: chrome/browser/cocoa/infobar_controller.mm

Issue 155494: First cut at infobars on Mac. These are not expected to be... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Name: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 <Cocoa/Cocoa.h>
6
7 #include "base/mac_util.h"
8 #include "base/sys_string_conversions.h"
9 #include "chrome/browser/cocoa/infobar.h"
10 #import "chrome/browser/cocoa/infobar_container_controller.h"
11 #import "chrome/browser/cocoa/infobar_controller.h"
12 #include "chrome/browser/tab_contents/tab_contents.h"
13 #include "skia/ext/skia_utils_mac.h"
14 #include "webkit/glue/window_open_disposition.h"
15
16
17 @interface InfoBarController (PrivateMethods)
18 // Closes the infobar by calling RemoveDelegate on the container.
19 // This will remove the infobar from its associated TabContents as
20 // well as trigger the deletion of this InfoBarController. Once the
21 // delegate is removed from the container, it is no longer needed, so
22 // we ask it to delete itself.
23 - (void)closeInfoBar;
24 @end
25
26 @implementation InfoBarController
27
28 @synthesize containerController = containerController_;
29 @synthesize delegate = delegate_;
30
31 - (id)initWithDelegate:(InfoBarDelegate*)delegate {
32 DCHECK(delegate);
33 if ((self = [super initWithNibName:@"InfoBar"
34 bundle:mac_util::MainAppBundle()])) {
35 delegate_ = delegate;
36 }
37 return self;
38 }
39
40 // All infobars have an icon, so we set up the icon in the base class
41 // awakeFromNib.
42 - (void)awakeFromNib {
43 if (delegate_->GetIcon()) {
44 [image_ setImage:gfx::SkBitmapToNSImage(*(delegate_->GetIcon()))];
45 }
46
47 [self addAdditionalControls];
48 }
49
50 // Called when someone clicks on the close button.
51 - (void)dismiss:(id)sender {
52 [self closeInfoBar];
53 }
54
55 - (void)addAdditionalControls {
56 // Default implementation does nothing.
57 }
58
59 @end
60
61 @implementation InfoBarController (PrivateMethods)
62 - (void)closeInfoBar {
63 // Calling RemoveDelegate() triggers notifications which will remove
64 // the infobar view from the infobar container. At that point it is
65 // safe to ask the delegate to delete itself.
66 DCHECK(delegate_);
67 [containerController_ removeDelegate:delegate_];
68 delegate_->InfoBarClosed();
69 delegate_ = NULL;
70 }
71 @end
72
73
74 /////////////////////////////////////////////////////////////////////////
75 // AlertInfoBarController implementation
76
77 @implementation AlertInfoBarController
78
79 // Alert infobars have a text message.
80 - (void)addAdditionalControls {
81 AlertInfoBarDelegate* delegate = delegate_->AsAlertInfoBarDelegate();
82 [label_ setStringValue:base::SysWideToNSString(
83 delegate->GetMessageText())];
84 }
85
86 @end
87
88
89 /////////////////////////////////////////////////////////////////////////
90 // LinkInfoBarController implementation
91
92 @implementation LinkInfoBarController
93
94 // Link infobars have a text message, of which part is linkified. We
95 // use an NSAttributedString to display styled text, and we set a
96 // NSLink attribute on the hyperlink portion of the message. Infobars
97 // use a custom NSTextField subclass, which allows us to override
98 // textView:clickedOnLink:atIndex: and intercept clicks.
99 //
100 // TODO(rohitrao): Using an NSTextField here has some weird UI side
101 // effects, such as showing the wrong cursor at times. Explore other
102 // solutions.
103 - (void)addAdditionalControls {
104 LinkInfoBarDelegate* delegate = delegate_->AsLinkInfoBarDelegate();
105 size_t offset = std::wstring::npos;
106 std::wstring message = delegate->GetMessageTextWithOffset(&offset);
107
108 // Create an attributes dictionary for the entire message. We have
109 // to expicitly set the font to the system font, because
110 // NSAttributedString defaults to Helvetica 12. We also override
111 // the cursor to give us the normal cursor rather than the text
112 // insertion cursor.
113 NSMutableDictionary* linkAttributes =
114 [NSMutableDictionary dictionaryWithObject:[NSCursor arrowCursor]
115 forKey:NSCursorAttributeName];
116 [linkAttributes setObject:[NSFont systemFontOfSize:[NSFont systemFontSize]]
117 forKey:NSFontAttributeName];
118
119 // Create the attributed string for the main message text.
120 NSMutableAttributedString* infoText =
121 [[NSMutableAttributedString alloc]
122 initWithString:base::SysWideToNSString(message)];
123 [infoText addAttributes:linkAttributes
124 range:NSMakeRange(0, [infoText length])];
125
126 // Add additional attributes to style the link text appropriately as
127 // well as linkify it. We use an empty string for the NSLink
128 // attribute because the actual object we pass doesn't matter, but
129 // it cannot be nil.
130 [linkAttributes setObject:[NSColor blueColor]
131 forKey:NSForegroundColorAttributeName];
132 [linkAttributes setObject:[NSNumber numberWithBool:YES]
133 forKey:NSUnderlineStyleAttributeName];
134 [linkAttributes setObject:[NSCursor pointingHandCursor]
135 forKey:NSCursorAttributeName];
136 [linkAttributes setObject:[NSString string] // dummy value
137 forKey:NSLinkAttributeName];
138
139 // Insert the link text into the string at the appropriate offset.
140 [infoText insertAttributedString:
141 [[[NSAttributedString alloc]
142 initWithString:base::SysWideToNSString(delegate->GetLinkText())
143 attributes:linkAttributes] autorelease]
144 atIndex:offset];
145
146 // Update the label view with the new text. The view must be
147 // selectable and allow editing text attributes for the
148 // linkification to work correctly.
149 [label_ setAllowsEditingTextAttributes: YES];
150 [label_ setSelectable: YES];
151 [label_ setAttributedStringValue:infoText];
152 }
153
154 // Called when someone clicks on the link in the infobar. This method
155 // is called by the InfobarTextField on its delegate (the
156 // LinkInfoBarController).
157 - (void)linkClicked {
158 // TODO(rohitrao): Set the disposition correctly based on modifier keys.
159 WindowOpenDisposition disposition = CURRENT_TAB;
160 if (delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition))
161 [self closeInfoBar];
162 }
163
164 @end
165
166
167 /////////////////////////////////////////////////////////////////////////
168 // ConfirmInfoBarController implementation
169
170 @implementation ConfirmInfoBarController
171
172 // Called when someone clicks on the "OK" button.
173 - (IBAction)ok:(id)sender {
174 if (delegate_->AsConfirmInfoBarDelegate()->Accept())
175 [self closeInfoBar];
176 }
177
178 // Called when someone clicks on the "Cancel" button.
179 - (IBAction)cancel:(id)sender {
180 if (delegate_->AsConfirmInfoBarDelegate()->Cancel())
181 [self closeInfoBar];
182 }
183
184 // Confirm infobars can have OK and/or cancel buttons, depending on
185 // the return value of GetButtons(). We create each button if
186 // required and position them to the left of the close button.
187 - (void)addAdditionalControls {
188 ConfirmInfoBarDelegate* delegate = delegate_->AsConfirmInfoBarDelegate();
189 [label_ setStringValue:base::SysWideToNSString(delegate->GetMessageText())];
190
191 int visibleButtons = delegate->GetButtons();
192 NSButton *okButton = nil;
193 NSButton *cancelButton = nil;
194
195 // Create the OK button if needed.
196 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) {
197 okButton = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
198 [okButton setBezelStyle:NSRoundedBezelStyle];
199 [okButton setTitle:base::SysWideToNSString(
200 delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))];
201 [okButton sizeToFit];
202 [okButton setAutoresizingMask:NSViewMinXMargin];
203 [okButton setTarget:self];
204 [okButton setAction:@selector(ok:)];
205 }
206
207 // Create the cancel button if needed.
208 if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
209 cancelButton = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
210 [cancelButton setBezelStyle:NSRoundedBezelStyle];
211 [cancelButton setTitle:base::SysWideToNSString(
212 delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))];
213 [cancelButton sizeToFit];
214 [cancelButton setAutoresizingMask:NSViewMinXMargin];
215 [cancelButton setTarget:self];
216 [cancelButton setAction:@selector(cancel:)];
217 }
218
219 // Position the cancel button, if it exists.
220 int cancelWidth = 0;
221 if (cancelButton) {
222 NSRect cancelFrame = [cancelButton frame];
223 cancelWidth = cancelFrame.size.width + 10;
224
225 // Position the cancel button to the left of the close button. A 10px
226 // margin is already built into cancelWidth.
227 cancelFrame.origin.x = NSMinX([closeButton_ frame]) - cancelWidth;
228 cancelFrame.origin.y = 0;
229 [cancelButton setFrame:cancelFrame];
230 [[self view] addSubview:cancelButton];
231
232 // Resize the label box to extend all the way to the cancel button,
233 // minus a 10px argin.
234 NSRect labelFrame = [label_ frame];
235 labelFrame.size.width = NSMinX(cancelFrame) - 10 - NSMinX(labelFrame);
236 [label_ setFrame:labelFrame];
237 }
238
239 // Position the OK button, if it exists.
240 if (okButton) {
241 NSRect okFrame = [okButton frame];
242 int okWidth = okFrame.size.width + 10;
243
244 // Position the OK button to the left of the close button as
245 // well. If a cancel button is present, |cancelWidth| will be positive.
246 // In either case, a 10px margin is built into okWidth.
247 okFrame.origin.x =
248 NSMinX([closeButton_ frame]) - cancelWidth - okWidth;
249 okFrame.origin.y = 0;
250 [okButton setFrame:okFrame];
251 [[self view] addSubview:okButton];
252
253 // Resize the label box to extend all the way to the OK button,
254 // minus a 10px argin.
255 NSRect labelFrame = [label_ frame];
256 labelFrame.size.width = NSMinX(okFrame) - 10 - NSMinX(labelFrame);
257 [label_ setFrame:labelFrame];
258 }
259 }
260
261 @end
262
263
264 //////////////////////////////////////////////////////////////////////////
265 // CreateInfoBar() implementations
266
267 InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
268 AlertInfoBarController* controller =
269 [[AlertInfoBarController alloc] initWithDelegate:this];
270 return new InfoBar(controller);
271 }
272
273 InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
274 LinkInfoBarController* controller =
275 [[LinkInfoBarController alloc] initWithDelegate:this];
276 return new InfoBar(controller);
277 }
278
279 InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
280 ConfirmInfoBarController* controller =
281 [[ConfirmInfoBarController alloc] initWithDelegate:this];
282 return new InfoBar(controller);
283 }
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/infobar_controller.h ('k') | chrome/browser/cocoa/infobar_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698