summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/popup_blocked_animation_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa/popup_blocked_animation_mac.mm')
-rw-r--r--chrome/browser/cocoa/popup_blocked_animation_mac.mm160
1 files changed, 160 insertions, 0 deletions
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 0000000..cee6812
--- /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];
+}