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

Unified Diff: chrome/browser/ui/cocoa/infobar_controller.mm

Issue 6377001: [Mac] Organize all infobar files into chrome/browser/ui/cocoa/infobars/.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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
Index: chrome/browser/ui/cocoa/infobar_controller.mm
===================================================================
--- chrome/browser/ui/cocoa/infobar_controller.mm (revision 71658)
+++ chrome/browser/ui/cocoa/infobar_controller.mm (working copy)
@@ -1,537 +0,0 @@
-// Copyright (c) 2010 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/logging.h" // for NOTREACHED()
-#include "base/mac/mac_util.h"
-#include "base/sys_string_conversions.h"
-#include "chrome/browser/tab_contents/infobar_delegate.h"
-#import "chrome/browser/ui/cocoa/animatable_view.h"
-#include "chrome/browser/ui/cocoa/event_utils.h"
-#include "chrome/browser/ui/cocoa/infobar.h"
-#import "chrome/browser/ui/cocoa/infobar_container_controller.h"
-#import "chrome/browser/ui/cocoa/infobar_controller.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-#include "webkit/glue/window_open_disposition.h"
-
-namespace {
-// Durations set to match the default SlideAnimation duration.
-const float kAnimateOpenDuration = 0.12;
-const float kAnimateCloseDuration = 0.12;
-}
-
-// This simple subclass of |NSTextView| just doesn't show the (text) cursor
-// (|NSTextView| displays the cursor with full keyboard accessibility enabled).
-@interface InfoBarTextView : NSTextView
-- (void)fixupCursor;
-@end
-
-@implementation InfoBarTextView
-
-// Never draw the insertion point (otherwise, it shows up without any user
-// action if full keyboard accessibility is enabled).
-- (BOOL)shouldDrawInsertionPoint {
- return NO;
-}
-
-- (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange
- granularity:(NSSelectionGranularity)granularity {
- // Do not allow selections.
- return NSMakeRange(0, 0);
-}
-
-// Convince NSTextView to not show an I-Beam cursor when the cursor is over the
-// text view but not over actual text.
-//
-// http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10791.html
-// "NSTextView sets the cursor over itself dynamically, based on considerations
-// including the text under the cursor. It does so in -mouseEntered:,
-// -mouseMoved:, and -cursorUpdate:, so those would be points to consider
-// overriding."
-- (void)mouseMoved:(NSEvent*)e {
- [super mouseMoved:e];
- [self fixupCursor];
-}
-
-- (void)mouseEntered:(NSEvent*)e {
- [super mouseEntered:e];
- [self fixupCursor];
-}
-
-- (void)cursorUpdate:(NSEvent*)e {
- [super cursorUpdate:e];
- [self fixupCursor];
-}
-
-- (void)fixupCursor {
- if ([[NSCursor currentCursor] isEqual:[NSCursor IBeamCursor]])
- [[NSCursor arrowCursor] set];
-}
-
-@end
-
-@interface InfoBarController (PrivateMethods)
-// Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil.
-- (void)initializeLabel;
-
-// Asks the container controller to remove the infobar for this delegate. This
-// call will trigger a notification that starts the infobar animating closed.
-- (void)removeInfoBar;
-
-// Performs final cleanup after an animation is finished or stopped, including
-// notifying the InfoBarDelegate that the infobar was closed and removing the
-// infobar from its container, if necessary.
-- (void)cleanUpAfterAnimation:(BOOL)finished;
-
-// Sets the info bar message to the specified |message|, with a hypertext
-// style link. |link| will be inserted into message at |linkOffset|.
-- (void)setLabelToMessage:(NSString*)message
- withLink:(NSString*)link
- atOffset:(NSUInteger)linkOffset;
-@end
-
-@implementation InfoBarController
-
-@synthesize containerController = containerController_;
-@synthesize delegate = delegate_;
-
-- (id)initWithDelegate:(InfoBarDelegate*)delegate {
- DCHECK(delegate);
- if ((self = [super initWithNibName:@"InfoBar"
- bundle:base::mac::MainAppBundle()])) {
- delegate_ = delegate;
- }
- return self;
-}
-
-// All infobars have an icon, so we set up the icon in the base class
-// awakeFromNib.
-- (void)awakeFromNib {
- DCHECK(delegate_);
- if (delegate_->GetIcon()) {
- [image_ setImage:gfx::SkBitmapToNSImage(*(delegate_->GetIcon()))];
- } else {
- // No icon, remove it from the view and grow the textfield to include the
- // space.
- NSRect imageFrame = [image_ frame];
- NSRect labelFrame = [labelPlaceholder_ frame];
- labelFrame.size.width += NSMinX(imageFrame) - NSMinX(labelFrame);
- labelFrame.origin.x = imageFrame.origin.x;
- [image_ removeFromSuperview];
- [labelPlaceholder_ setFrame:labelFrame];
- }
- [self initializeLabel];
-
- [self addAdditionalControls];
-}
-
-// Called when someone clicks on the embedded link.
-- (BOOL) textView:(NSTextView*)textView
- clickedOnLink:(id)link
- atIndex:(NSUInteger)charIndex {
- if ([self respondsToSelector:@selector(linkClicked)])
- [self performSelector:@selector(linkClicked)];
- return YES;
-}
-
-// Called when someone clicks on the ok button.
-- (void)ok:(id)sender {
- // Subclasses must override this method if they do not hide the ok button.
- NOTREACHED();
-}
-
-// Called when someone clicks on the cancel button.
-- (void)cancel:(id)sender {
- // Subclasses must override this method if they do not hide the cancel button.
- NOTREACHED();
-}
-
-// Called when someone clicks on the close button.
-- (void)dismiss:(id)sender {
- [self removeInfoBar];
-}
-
-- (AnimatableView*)animatableView {
- return static_cast<AnimatableView*>([self view]);
-}
-
-- (void)open {
- // Simply reset the frame size to its opened size, forcing a relayout.
- CGFloat finalHeight = [[self view] frame].size.height;
- [[self animatableView] setHeight:finalHeight];
-}
-
-- (void)animateOpen {
- // Force the frame size to be 0 and then start an animation.
- NSRect frame = [[self view] frame];
- CGFloat finalHeight = frame.size.height;
- frame.size.height = 0;
- [[self view] setFrame:frame];
- [[self animatableView] animateToNewHeight:finalHeight
- duration:kAnimateOpenDuration];
-}
-
-- (void)close {
- // Stop any running animations.
- [[self animatableView] stopAnimation];
- infoBarClosing_ = YES;
- [self cleanUpAfterAnimation:YES];
-}
-
-- (void)animateClosed {
- // Start animating closed. We will receive a notification when the animation
- // is done, at which point we can remove our view from the hierarchy and
- // notify the delegate that the infobar was closed.
- [[self animatableView] animateToNewHeight:0 duration:kAnimateCloseDuration];
-
- // The above call may trigger an animationDidStop: notification for any
- // currently-running animations, so do not set |infoBarClosing_| until after
- // starting the animation.
- infoBarClosing_ = YES;
-}
-
-- (void)addAdditionalControls {
- // Default implementation does nothing.
-}
-
-- (void)infobarWillClose {
- // Default implementation does nothing.
-}
-
-- (void)setLabelToMessage:(NSString*)message {
- NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
- NSFont* font = [NSFont labelFontOfSize:
- [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
- [attributes setObject:font
- forKey:NSFontAttributeName];
- [attributes setObject:[NSCursor arrowCursor]
- forKey:NSCursorAttributeName];
- scoped_nsobject<NSAttributedString> attributedString(
- [[NSAttributedString alloc] initWithString:message
- attributes:attributes]);
- [[label_.get() textStorage] setAttributedString:attributedString];
-}
-
-- (void)removeButtons {
- // Extend the label all the way across.
- NSRect labelFrame = [label_.get() frame];
- labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame);
- [okButton_ removeFromSuperview];
- [cancelButton_ removeFromSuperview];
- [label_.get() setFrame:labelFrame];
-}
-
-@end
-
-@implementation InfoBarController (PrivateMethods)
-
-- (void)initializeLabel {
- // Replace the label placeholder NSTextField with the real label NSTextView.
- // The former doesn't show links in a nice way, but the latter can't be added
- // in IB without a containing scroll view, so create the NSTextView
- // programmatically.
- label_.reset([[InfoBarTextView alloc]
- initWithFrame:[labelPlaceholder_ frame]]);
- [label_.get() setAutoresizingMask:[labelPlaceholder_ autoresizingMask]];
- [[labelPlaceholder_ superview]
- replaceSubview:labelPlaceholder_ with:label_.get()];
- labelPlaceholder_ = nil; // Now released.
- [label_.get() setDelegate:self];
- [label_.get() setEditable:NO];
- [label_.get() setDrawsBackground:NO];
- [label_.get() setHorizontallyResizable:NO];
- [label_.get() setVerticallyResizable:NO];
-}
-
-- (void)removeInfoBar {
- // TODO(rohitrao): This method can be called even if the infobar has already
- // been removed and |delegate_| is NULL. Is there a way to rewrite the code
- // so that inner event loops don't cause us to try and remove the infobar
- // twice? http://crbug.com/54253
- [containerController_ removeDelegate:delegate_];
-}
-
-- (void)cleanUpAfterAnimation:(BOOL)finished {
- // Don't need to do any cleanup if the bar was animating open.
- if (!infoBarClosing_)
- return;
-
- // Notify the delegate that the infobar was closed. The delegate may delete
- // itself as a result of InfoBarClosed(), so we null out its pointer.
- if (delegate_) {
- delegate_->InfoBarClosed();
- delegate_ = NULL;
- }
-
- // If the animation ran to completion, then we need to remove ourselves from
- // the container. If the animation was interrupted, then the container will
- // take care of removing us.
- // TODO(rohitrao): UGH! This works for now, but should be cleaner.
- if (finished)
- [containerController_ removeController:self];
-}
-
-- (void)animationDidStop:(NSAnimation*)animation {
- [self cleanUpAfterAnimation:NO];
-}
-
-- (void)animationDidEnd:(NSAnimation*)animation {
- [self cleanUpAfterAnimation:YES];
-}
-
-// TODO(joth): This method factors out some common functionality between the
-// various derived infobar classes, however the class hierarchy itself could
-// use refactoring to reduce this duplication. http://crbug.com/38924
-- (void)setLabelToMessage:(NSString*)message
- withLink:(NSString*)link
- atOffset:(NSUInteger)linkOffset {
- if (linkOffset == std::wstring::npos) {
- // linkOffset == std::wstring::npos means the link should be right-aligned,
- // which is not supported on Mac (http://crbug.com/47728).
- NOTIMPLEMENTED();
- linkOffset = [message length];
- }
- // Create an attributes dictionary for the entire message. We have
- // to expicitly set the font the control's font. We also override
- // the cursor to give us the normal cursor rather than the text
- // insertion cursor.
- NSMutableDictionary* linkAttributes = [NSMutableDictionary dictionary];
- [linkAttributes setObject:[NSCursor arrowCursor]
- forKey:NSCursorAttributeName];
- NSFont* font = [NSFont labelFontOfSize:
- [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
- [linkAttributes setObject:font
- forKey:NSFontAttributeName];
-
- // Create the attributed string for the main message text.
- scoped_nsobject<NSMutableAttributedString> infoText(
- [[NSMutableAttributedString alloc] initWithString:message]);
- [infoText.get() addAttributes:linkAttributes
- range:NSMakeRange(0, [infoText.get() length])];
- // Add additional attributes to style the link text appropriately as
- // well as linkify it.
- [linkAttributes setObject:[NSColor blueColor]
- forKey:NSForegroundColorAttributeName];
- [linkAttributes setObject:[NSNumber numberWithBool:YES]
- forKey:NSUnderlineStyleAttributeName];
- [linkAttributes setObject:[NSCursor pointingHandCursor]
- forKey:NSCursorAttributeName];
- [linkAttributes setObject:[NSNumber numberWithInt:NSSingleUnderlineStyle]
- forKey:NSUnderlineStyleAttributeName];
- [linkAttributes setObject:[NSString string] // dummy value
- forKey:NSLinkAttributeName];
-
- // Insert the link text into the string at the appropriate offset.
- scoped_nsobject<NSAttributedString> attributedString(
- [[NSAttributedString alloc] initWithString:link
- attributes:linkAttributes]);
- [infoText.get() insertAttributedString:attributedString.get()
- atIndex:linkOffset];
- // Update the label view with the new text.
- [[label_.get() textStorage] setAttributedString:infoText];
-}
-
-@end
-
-
-/////////////////////////////////////////////////////////////////////////
-// AlertInfoBarController implementation
-
-@implementation AlertInfoBarController
-
-// Alert infobars have a text message.
-- (void)addAdditionalControls {
- // No buttons.
- [self removeButtons];
-
- // Insert the text.
- AlertInfoBarDelegate* delegate = delegate_->AsAlertInfoBarDelegate();
- DCHECK(delegate);
- [self setLabelToMessage:base::SysUTF16ToNSString(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.
-//
-- (void)addAdditionalControls {
- // No buttons.
- [self removeButtons];
-
- LinkInfoBarDelegate* delegate = delegate_->AsLinkInfoBarDelegate();
- DCHECK(delegate);
- size_t offset = std::wstring::npos;
- string16 message = delegate->GetMessageTextWithOffset(&offset);
- [self setLabelToMessage:base::SysUTF16ToNSString(message)
- withLink:base::SysUTF16ToNSString(delegate->GetLinkText())
- atOffset:offset];
-}
-
-// Called when someone clicks on the link in the infobar. This method
-// is called by the InfobarTextField on its delegate (the
-// LinkInfoBarController).
-- (void)linkClicked {
- WindowOpenDisposition disposition =
- event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
- if (delegate_ && delegate_->AsLinkInfoBarDelegate()->LinkClicked(disposition))
- [self removeInfoBar];
-}
-
-@end
-
-
-/////////////////////////////////////////////////////////////////////////
-// ConfirmInfoBarController implementation
-
-@implementation ConfirmInfoBarController
-
-// Called when someone clicks on the "OK" button.
-- (IBAction)ok:(id)sender {
- if (delegate_ && delegate_->AsConfirmInfoBarDelegate()->Accept())
- [self removeInfoBar];
-}
-
-// Called when someone clicks on the "Cancel" button.
-- (IBAction)cancel:(id)sender {
- if (delegate_ && delegate_->AsConfirmInfoBarDelegate()->Cancel())
- [self removeInfoBar];
-}
-
-// 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();
- DCHECK(delegate);
- int visibleButtons = delegate->GetButtons();
-
- NSRect okButtonFrame = [okButton_ frame];
- NSRect cancelButtonFrame = [cancelButton_ frame];
-
- DCHECK(NSMaxX(okButtonFrame) < NSMinX(cancelButtonFrame))
- << "Cancel button expected to be on the right of the Ok button in nib";
-
- CGFloat rightEdge = NSMaxX(cancelButtonFrame);
- CGFloat spaceBetweenButtons =
- NSMinX(cancelButtonFrame) - NSMaxX(okButtonFrame);
- CGFloat spaceBeforeButtons =
- NSMinX(okButtonFrame) - NSMaxX([label_.get() frame]);
-
- // Update and position the Cancel button if needed. Otherwise, hide it.
- if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
- [cancelButton_ setTitle:base::SysUTF16ToNSString(
- delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))];
- [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_];
- cancelButtonFrame = [cancelButton_ frame];
-
- // Position the cancel button to the left of the Close button.
- cancelButtonFrame.origin.x = rightEdge - cancelButtonFrame.size.width;
- [cancelButton_ setFrame:cancelButtonFrame];
-
- // Update the rightEdge
- rightEdge = NSMinX(cancelButtonFrame);
- } else {
- [cancelButton_ removeFromSuperview];
- }
-
- // Update and position the OK button if needed. Otherwise, hide it.
- if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) {
- [okButton_ setTitle:base::SysUTF16ToNSString(
- delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))];
- [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_];
- okButtonFrame = [okButton_ frame];
-
- // If we had a Cancel button, leave space between the buttons.
- if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
- rightEdge -= spaceBetweenButtons;
- }
-
- // Position the OK button on our current right edge.
- okButtonFrame.origin.x = rightEdge - okButtonFrame.size.width;
- [okButton_ setFrame:okButtonFrame];
-
-
- // Update the rightEdge
- rightEdge = NSMinX(okButtonFrame);
- } else {
- [okButton_ removeFromSuperview];
- }
-
- // If we had either button, leave space before the edge of the textfield.
- if ((visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) ||
- (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK)) {
- rightEdge -= spaceBeforeButtons;
- }
-
- NSRect frame = [label_.get() frame];
- DCHECK(rightEdge > NSMinX(frame))
- << "Need to make the xib larger to handle buttons with text this long";
- frame.size.width = rightEdge - NSMinX(frame);
- [label_.get() setFrame:frame];
-
- // Set the text and link.
- NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText());
- string16 link = delegate->GetLinkText();
- if (link.empty()) {
- // Simple case: no link, so just set the message directly.
- [self setLabelToMessage:message];
- } else {
- // Inserting the link unintentionally causes the text to have a slightly
- // different result to the simple case above: text is truncated on word
- // boundaries (if needed) rather than elided with ellipses.
-
- // Add spacing between the label and the link.
- message = [message stringByAppendingString:@" "];
- [self setLabelToMessage:message
- withLink:base::SysUTF16ToNSString(link)
- atOffset:[message length]];
- }
-}
-
-// Called when someone clicks on the link in the infobar. This method
-// is called by the InfobarTextField on its delegate (the
-// LinkInfoBarController).
-- (void)linkClicked {
- WindowOpenDisposition disposition =
- event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
- if (delegate_ &&
- delegate_->AsConfirmInfoBarDelegate()->LinkClicked(disposition))
- [self removeInfoBar];
-}
-
-@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);
-}
« no previous file with comments | « chrome/browser/ui/cocoa/infobar_controller.h ('k') | chrome/browser/ui/cocoa/infobar_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698