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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/cocoa/infobar_controller.mm
===================================================================
--- chrome/browser/cocoa/infobar_controller.mm (revision 0)
+++ chrome/browser/cocoa/infobar_controller.mm (revision 0)
@@ -0,0 +1,283 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/cocoa/infobar.h"
+#import "chrome/browser/cocoa/infobar_container_controller.h"
+#import "chrome/browser/cocoa/infobar_controller.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "skia/ext/skia_utils_mac.h"
+#include "webkit/glue/window_open_disposition.h"
+
+
+@interface InfoBarController (PrivateMethods)
+// Closes the infobar by calling RemoveDelegate on the container.
+// This will remove the infobar from its associated TabContents as
+// well as trigger the deletion of this InfoBarController. Once the
+// delegate is removed from the container, it is no longer needed, so
+// we ask it to delete itself.
+- (void)closeInfoBar;
+@end
+
+@implementation InfoBarController
+
+@synthesize containerController = containerController_;
+@synthesize delegate = delegate_;
+
+- (id)initWithDelegate:(InfoBarDelegate*)delegate {
+ DCHECK(delegate);
+ if ((self = [super initWithNibName:@"InfoBar"
+ bundle:mac_util::MainAppBundle()])) {
+ delegate_ = delegate;
+ }
+ return self;
+}
+
+// All infobars have an icon, so we set up the icon in the base class
+// awakeFromNib.
+- (void)awakeFromNib {
+ if (delegate_->GetIcon()) {
+ [image_ setImage:gfx::SkBitmapToNSImage(*(delegate_->GetIcon()))];
+ }
+
+ [self addAdditionalControls];
+}
+
+// Called when someone clicks on the close button.
+- (void)dismiss:(id)sender {
+ [self closeInfoBar];
+}
+
+- (void)addAdditionalControls {
+ // Default implementation does nothing.
+}
+
+@end
+
+@implementation InfoBarController (PrivateMethods)
+- (void)closeInfoBar {
+ // Calling RemoveDelegate() triggers notifications which will remove
+ // the infobar view from the infobar container. At that point it is
+ // safe to ask the delegate to delete itself.
+ DCHECK(delegate_);
+ [containerController_ removeDelegate:delegate_];
+ delegate_->InfoBarClosed();
+ delegate_ = NULL;
+}
+@end
+
+
+/////////////////////////////////////////////////////////////////////////
+// AlertInfoBarController implementation
+
+@implementation AlertInfoBarController
+
+// Alert infobars have a text message.
+- (void)addAdditionalControls {
+ AlertInfoBarDelegate* delegate = delegate_->AsAlertInfoBarDelegate();
+ [label_ setStringValue:base::SysWideToNSString(
+ delegate->GetMessageText())];
+}
+
+@end
+
+
+/////////////////////////////////////////////////////////////////////////
+// LinkInfoBarController implementation
+
+@implementation LinkInfoBarController
+
+// Link infobars have a text message, of which part is linkified. We
+// use an NSAttributedString to display styled text, and we set a
+// NSLink attribute on the hyperlink portion of the message. Infobars
+// use a custom NSTextField subclass, which allows us to override
+// textView:clickedOnLink:atIndex: and intercept clicks.
+//
+// TODO(rohitrao): Using an NSTextField here has some weird UI side
+// effects, such as showing the wrong cursor at times. Explore other
+// solutions.
+- (void)addAdditionalControls {
+ LinkInfoBarDelegate* delegate = delegate_->AsLinkInfoBarDelegate();
+ size_t offset = std::wstring::npos;
+ std::wstring message = delegate->GetMessageTextWithOffset(&offset);
+
+ // Create an attributes dictionary for the entire message. We have
+ // to expicitly set the font to the system font, because
+ // NSAttributedString defaults to Helvetica 12. We also override
+ // the cursor to give us the normal cursor rather than the text
+ // insertion cursor.
+ NSMutableDictionary* linkAttributes =
+ [NSMutableDictionary dictionaryWithObject:[NSCursor arrowCursor]
+ forKey:NSCursorAttributeName];
+ [linkAttributes setObject:[NSFont systemFontOfSize:[NSFont systemFontSize]]
+ forKey:NSFontAttributeName];
+
+ // Create the attributed string for the main message text.
+ NSMutableAttributedString* infoText =
+ [[NSMutableAttributedString alloc]
+ initWithString:base::SysWideToNSString(message)];
+ [infoText addAttributes:linkAttributes
+ range:NSMakeRange(0, [infoText length])];
+
+ // Add additional attributes to style the link text appropriately as
+ // well as linkify it. We use an empty string for the NSLink
+ // attribute because the actual object we pass doesn't matter, but
+ // it cannot be nil.
+ [linkAttributes setObject:[NSColor blueColor]
+ forKey:NSForegroundColorAttributeName];
+ [linkAttributes setObject:[NSNumber numberWithBool:YES]
+ forKey:NSUnderlineStyleAttributeName];
+ [linkAttributes setObject:[NSCursor pointingHandCursor]
+ forKey:NSCursorAttributeName];
+ [linkAttributes setObject:[NSString string] // dummy value
+ forKey:NSLinkAttributeName];
+
+ // Insert the link text into the string at the appropriate offset.
+ [infoText insertAttributedString:
+ [[[NSAttributedString alloc]
+ initWithString:base::SysWideToNSString(delegate->GetLinkText())
+ attributes:linkAttributes] autorelease]
+ atIndex:offset];
+
+ // Update the label view with the new text. The view must be
+ // selectable and allow editing text attributes for the
+ // linkification to work correctly.
+ [label_ setAllowsEditingTextAttributes: YES];
+ [label_ setSelectable: YES];
+ [label_ setAttributedStringValue:infoText];
+}
+
+// Called when someone clicks on the link in the infobar. This method
+// is called by the InfobarTextField on its delegate (the
+// LinkInfoBarController).
+- (void)linkClicked {
+ // TODO(rohitrao): Set the disposition correctly based on modifier keys.
+ WindowOpenDisposition disposition = CURRENT_TAB;
+ if (delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition))
+ [self closeInfoBar];
+}
+
+@end
+
+
+/////////////////////////////////////////////////////////////////////////
+// ConfirmInfoBarController implementation
+
+@implementation ConfirmInfoBarController
+
+// Called when someone clicks on the "OK" button.
+- (IBAction)ok:(id)sender {
+ if (delegate_->AsConfirmInfoBarDelegate()->Accept())
+ [self closeInfoBar];
+}
+
+// Called when someone clicks on the "Cancel" button.
+- (IBAction)cancel:(id)sender {
+ if (delegate_->AsConfirmInfoBarDelegate()->Cancel())
+ [self closeInfoBar];
+}
+
+// Confirm infobars can have OK and/or cancel buttons, depending on
+// the return value of GetButtons(). We create each button if
+// required and position them to the left of the close button.
+- (void)addAdditionalControls {
+ ConfirmInfoBarDelegate* delegate = delegate_->AsConfirmInfoBarDelegate();
+ [label_ setStringValue:base::SysWideToNSString(delegate->GetMessageText())];
+
+ int visibleButtons = delegate->GetButtons();
+ NSButton *okButton = nil;
+ NSButton *cancelButton = nil;
+
+ // Create the OK button if needed.
+ if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) {
+ okButton = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
+ [okButton setBezelStyle:NSRoundedBezelStyle];
+ [okButton setTitle:base::SysWideToNSString(
+ delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))];
+ [okButton sizeToFit];
+ [okButton setAutoresizingMask:NSViewMinXMargin];
+ [okButton setTarget:self];
+ [okButton setAction:@selector(ok:)];
+ }
+
+ // Create the cancel button if needed.
+ if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
+ cancelButton = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
+ [cancelButton setBezelStyle:NSRoundedBezelStyle];
+ [cancelButton setTitle:base::SysWideToNSString(
+ delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))];
+ [cancelButton sizeToFit];
+ [cancelButton setAutoresizingMask:NSViewMinXMargin];
+ [cancelButton setTarget:self];
+ [cancelButton setAction:@selector(cancel:)];
+ }
+
+ // Position the cancel button, if it exists.
+ int cancelWidth = 0;
+ if (cancelButton) {
+ NSRect cancelFrame = [cancelButton frame];
+ cancelWidth = cancelFrame.size.width + 10;
+
+ // Position the cancel button to the left of the close button. A 10px
+ // margin is already built into cancelWidth.
+ cancelFrame.origin.x = NSMinX([closeButton_ frame]) - cancelWidth;
+ cancelFrame.origin.y = 0;
+ [cancelButton setFrame:cancelFrame];
+ [[self view] addSubview:cancelButton];
+
+ // Resize the label box to extend all the way to the cancel button,
+ // minus a 10px argin.
+ NSRect labelFrame = [label_ frame];
+ labelFrame.size.width = NSMinX(cancelFrame) - 10 - NSMinX(labelFrame);
+ [label_ setFrame:labelFrame];
+ }
+
+ // Position the OK button, if it exists.
+ if (okButton) {
+ NSRect okFrame = [okButton frame];
+ int okWidth = okFrame.size.width + 10;
+
+ // Position the OK button to the left of the close button as
+ // well. If a cancel button is present, |cancelWidth| will be positive.
+ // In either case, a 10px margin is built into okWidth.
+ okFrame.origin.x =
+ NSMinX([closeButton_ frame]) - cancelWidth - okWidth;
+ okFrame.origin.y = 0;
+ [okButton setFrame:okFrame];
+ [[self view] addSubview:okButton];
+
+ // Resize the label box to extend all the way to the OK button,
+ // minus a 10px argin.
+ NSRect labelFrame = [label_ frame];
+ labelFrame.size.width = NSMinX(okFrame) - 10 - NSMinX(labelFrame);
+ [label_ setFrame:labelFrame];
+ }
+}
+
+@end
+
+
+//////////////////////////////////////////////////////////////////////////
+// CreateInfoBar() implementations
+
+InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
+ AlertInfoBarController* controller =
+ [[AlertInfoBarController alloc] initWithDelegate:this];
+ return new InfoBar(controller);
+}
+
+InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
+ LinkInfoBarController* controller =
+ [[LinkInfoBarController alloc] initWithDelegate:this];
+ return new InfoBar(controller);
+}
+
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
+ ConfirmInfoBarController* controller =
+ [[ConfirmInfoBarController alloc] initWithDelegate:this];
+ return new InfoBar(controller);
+}
Property changes on: chrome/browser/cocoa/infobar_controller.mm
___________________________________________________________________
Name: svn:eol-style
+ LF
« 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