| Index: chrome/browser/cocoa/popup_blocked_animation_mac.mm
|
| diff --git a/chrome/browser/cocoa/popup_blocked_animation_mac.mm b/chrome/browser/cocoa/popup_blocked_animation_mac.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cee68123611492eb56b868d711006151454ff49b
|
| --- /dev/null
|
| +++ b/chrome/browser/cocoa/popup_blocked_animation_mac.mm
|
| @@ -0,0 +1,160 @@
|
| +// 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.
|
| +
|
| +#include "chrome/browser/popup_blocked_animation.h"
|
| +
|
| +#import <Cocoa/Cocoa.h>
|
| +#import <QuartzCore/QuartzCore.h>
|
| +
|
| +#import "base/nsimage_cache_mac.h"
|
| +#import "chrome/browser/cocoa/animatable_image.h"
|
| +#include "chrome/browser/tab_contents/tab_contents.h"
|
| +#include "chrome/common/notification_registrar.h"
|
| +#include "chrome/common/notification_service.h"
|
| +
|
| +class PopupBlockedAnimationObserver;
|
| +
|
| +// A class for managing the Core Animation popup blocked animation.
|
| +@interface PopupBlockedAnimationMac : NSObject {
|
| + @private
|
| + // The observer for the TabContents we are drawing on.
|
| + scoped_ptr<PopupBlockedAnimationObserver> observer_;
|
| + AnimatableImage* animation_;
|
| +};
|
| +
|
| +// Called by our the Observer if the tab is hidden or closed.
|
| +- (void)animationComplete;
|
| +
|
| +@end
|
| +
|
| +// A helper class to monitor tab hidden and closed notifications. If we receive
|
| +// such a notification, we stop the animation.
|
| +class PopupBlockedAnimationObserver : public NotificationObserver {
|
| + public:
|
| + PopupBlockedAnimationObserver(PopupBlockedAnimationMac* owner,
|
| + TabContents* tab_contents)
|
| + : owner_(owner),
|
| + tab_contents_(tab_contents) {
|
| + registrar_.Add(this,
|
| + NotificationType::TAB_CONTENTS_HIDDEN,
|
| + Source<TabContents>(tab_contents_));
|
| + registrar_.Add(this,
|
| + NotificationType::TAB_CONTENTS_DESTROYED,
|
| + Source<TabContents>(tab_contents_));
|
| + }
|
| +
|
| + // Runs when a tab is hidden or destroyed. Let our owner know we should end
|
| + // the animation.
|
| + void Observe(NotificationType type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) {
|
| + // This ends up deleting us.
|
| + [owner_ animationComplete];
|
| + }
|
| +
|
| + private:
|
| + // The object we need to inform when we get a notification. Weak.
|
| + PopupBlockedAnimationMac* owner_;
|
| +
|
| + // The tab we are observing. Weak.
|
| + TabContents* tab_contents_;
|
| +
|
| + // Used for registering to receive notifications and automatic clean up.
|
| + NotificationRegistrar registrar_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(PopupBlockedAnimationObserver);
|
| +};
|
| +
|
| +@implementation PopupBlockedAnimationMac
|
| +
|
| +- (id)initWithTabContents:(TabContents*)tabContents {
|
| + if ((self = [super init])) {
|
| + NSImage* image = nsimage_cache::ImageNamed(@"popup_window_animation.pdf");
|
| + CGFloat imageWidth = [image size].width;
|
| + CGFloat imageHeight = [image size].height;
|
| +
|
| + NSView* tabContentsView = tabContents->GetNativeView();
|
| + NSWindow* parentWindow = [tabContentsView window];
|
| + if (!parentWindow) {
|
| + // The tab is no longer frontmost.
|
| + [self release];
|
| + return nil;
|
| + }
|
| +
|
| + NSRect windowFrame = [parentWindow frame];
|
| +
|
| + // Sanity check the size in case there's no room to display the animation.
|
| + if (imageWidth >= NSWidth(windowFrame) ||
|
| + imageHeight >= NSHeight(windowFrame)) {
|
| + [self release];
|
| + return nil;
|
| + }
|
| +
|
| + // Create the animation window to be the top-right quadrant of the window.
|
| + // The animation travels from the center of the window to the blocked
|
| + // content section of the Omnibox. This will release itself.
|
| + NSRect animationFrame = windowFrame;
|
| + CGFloat dX = NSWidth(animationFrame) / 2 - imageWidth / 2;
|
| + CGFloat dY = NSHeight(animationFrame) / 2 - imageHeight / 2;
|
| + animationFrame.origin.x += dX;
|
| + animationFrame.origin.y += dY;
|
| + animationFrame.size.width -= dX;
|
| + animationFrame.size.height -= dY;
|
| + animation_ = [[AnimatableImage alloc] initWithImage:image
|
| + animationFrame:animationFrame];
|
| + [parentWindow addChildWindow:animation_ ordered:NSWindowAbove];
|
| +
|
| + // Start the animation from the center of the window.
|
| + NSRect contentFrame = [[animation_ contentView] frame];
|
| + [animation_ setStartFrame:CGRectMake(0,
|
| + imageHeight / 2,
|
| + imageWidth,
|
| + imageHeight)];
|
| +
|
| + // Set the end frame to be small (a la the actual blocked icon) and inset
|
| + // slightly to the Omnibox. While the geometry won't align perfectly, it's
|
| + // close enough for the user to take note of the new icon. These numbers
|
| + // come from measuring the Omnibox without any page actions.
|
| + [animation_ setEndFrame:CGRectMake(animationFrame.size.width - 115,
|
| + animationFrame.size.height - 50,
|
| + 16, 16)];
|
| + [animation_ setStartOpacity:1.0];
|
| + [animation_ setEndOpacity:0.2];
|
| + [animation_ setDuration:0.7];
|
| +
|
| + observer_.reset(new PopupBlockedAnimationObserver(self, tabContents));
|
| +
|
| + // When the window is about to close, release this object and remove the
|
| + // animation from the parent window.
|
| + NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
|
| + [center addObserver:self
|
| + selector:@selector(windowWillClose:)
|
| + name:NSWindowWillCloseNotification
|
| + object:animation_];
|
| + [animation_ startAnimation];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)dealloc {
|
| + [[NSNotificationCenter defaultCenter] removeObserver:self];
|
| + [super dealloc];
|
| +}
|
| +
|
| +- (void)windowWillClose:(NSNotification*)notification {
|
| + DCHECK([[notification object] isEqual:animation_]);
|
| + [self animationComplete];
|
| +}
|
| +
|
| +- (void)animationComplete {
|
| + [[animation_ parentWindow] removeChildWindow:animation_];
|
| + [self release];
|
| +}
|
| +
|
| +@end
|
| +
|
| +void PopupBlockedAnimation::Show(TabContents* tab_contents) {
|
| + // The object will clean up itself at the end of the animation.
|
| + [[PopupBlockedAnimationMac alloc] initWithTabContents:tab_contents];
|
| +}
|
|
|