| 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
|
|
|
|
|