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

Unified Diff: chrome/browser/cocoa/download_started_animation_mac.mm

Issue 3014005: [Mac] Display a quick animation when a popup is blocked so the user notices it in the Omnibox. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: CGImage Created 10 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
Index: chrome/browser/cocoa/download_started_animation_mac.mm
diff --git a/chrome/browser/cocoa/download_started_animation_mac.mm b/chrome/browser/cocoa/download_started_animation_mac.mm
index 42c5c85bd42616e9f0d847cfa34db4ad0945b94f..f004469d3a6fb32da3c16b5881af20f5f826904e 100644
--- a/chrome/browser/cocoa/download_started_animation_mac.mm
+++ b/chrome/browser/cocoa/download_started_animation_mac.mm
@@ -15,6 +15,7 @@
#include "base/scoped_cftyperef.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view_mac.h"
+#import "chrome/browser/cocoa/animatable_image.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "grit/theme_resources.h"
@@ -25,11 +26,12 @@ class DownloadAnimationTabObserver;
// A class for managing the Core Animation download animation.
// Should be instantiated using +startAnimationWithTabContents:.
-@interface DownloadStartedAnimationMac : NSWindow {
+@interface DownloadStartedAnimationMac : NSObject {
@private
// The observer for the TabContents we are drawing on.
scoped_ptr<DownloadAnimationTabObserver> observer_;
CGFloat imageWidth_;
+ AnimatableImage* animation_;
};
+ (void)startAnimationWithTabContents:(TabContents*)tabContents;
@@ -41,7 +43,7 @@ class DownloadAnimationTabObserver;
// A helper class to monitor tab hidden and closed notifications. If we receive
// such a notification, we stop the animation.
class DownloadAnimationTabObserver : public NotificationObserver {
-public:
+ public:
DownloadAnimationTabObserver(DownloadStartedAnimationMac* owner,
TabContents* tab_contents)
: owner_(owner),
@@ -59,16 +61,11 @@ public:
void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- registrar_.Remove(this,
- NotificationType::TAB_CONTENTS_HIDDEN,
- Source<TabContents>(tab_contents_));
- registrar_.Remove(this,
- NotificationType::TAB_CONTENTS_DESTROYED,
- Source<TabContents>(tab_contents_));
+ // This ends up deleting us.
[owner_ animationComplete];
}
-private:
+ private:
// The object we need to inform when we get a notification. Weak.
DownloadStartedAnimationMac* owner_;
@@ -84,51 +81,56 @@ private:
@implementation DownloadStartedAnimationMac
- (id)initWithTabContents:(TabContents*)tabContents {
- // Load the image of the download arrow.
- ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
- SkBitmap* imageBitmap = bundle.GetBitmapNamed(IDR_DOWNLOAD_ANIMATION_BEGIN);
- scoped_cftyperef<CGImageRef> image(SkCreateCGImageRef(*imageBitmap));
-
- // Figure out the positioning in the current tab. Try to position the layer
- // against the left edge, and three times the download image's height from the
- // bottom of the tab, assuming there is enough room. If there isn't enough,
- // don't show the animation and let the shelf speak for itself.
- gfx::Rect bounds;
- tabContents->GetContainerBounds(&bounds);
- imageWidth_ = CGImageGetWidth(image);
- CGFloat imageHeight = CGImageGetHeight(image);
-
- // Sanity check the size in case there's no room to display the animation.
- if (bounds.height() < imageHeight) {
- [self release];
- return nil;
- }
-
- NSView* tabContentsView = tabContents->GetNativeView();
- NSWindow* parentWindow = [tabContentsView window];
- if (!parentWindow) {
- // The tab is no longer frontmost.
- [self release];
- return nil;
- }
-
- NSPoint origin = [tabContentsView frame].origin;
- origin = [tabContentsView convertPoint:origin toView:nil];
- origin = [parentWindow convertBaseToScreen:origin];
-
- // Create a window to host a layer that animates the sliding and fading.
- CGFloat animationHeight = MIN(bounds.height(), 4 * imageHeight);
- NSRect frame = NSMakeRect(origin.x, origin.y, imageWidth_, animationHeight);
- if ((self = [super initWithContentRect:frame
- styleMask:NSBorderlessWindowMask
- backing:NSBackingStoreBuffered
- defer:NO])) {
- [self setOpaque:NO];
- [self setBackgroundColor:[NSColor clearColor]];
- [self setIgnoresMouseEvents:YES];
+ if ((self = [super init])) {
+ // Load the image of the download arrow.
+ ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
+ SkBitmap* imageBitmap = bundle.GetBitmapNamed(IDR_DOWNLOAD_ANIMATION_BEGIN);
+ scoped_cftyperef<CGImageRef> image(SkCreateCGImageRef(*imageBitmap));
+
+ // Figure out the positioning in the current tab. Try to position the layer
+ // against the left edge, and three times the download image's height from
+ // the bottom of the tab, assuming there is enough room. If there isn't
+ // enough, don't show the animation and let the shelf speak for itself.
+ gfx::Rect bounds;
+ tabContents->GetContainerBounds(&bounds);
+ imageWidth_ = CGImageGetWidth(image);
+ CGFloat imageHeight = CGImageGetHeight(image);
+
+ // Sanity check the size in case there's no room to display the animation.
+ if (bounds.height() < imageHeight) {
+ [self release];
+ return nil;
+ }
+
+ NSView* tabContentsView = tabContents->GetNativeView();
+ NSWindow* parentWindow = [tabContentsView window];
+ if (!parentWindow) {
+ // The tab is no longer frontmost.
+ [self release];
+ return nil;
+ }
+
+ NSPoint origin = [tabContentsView frame].origin;
+ origin = [tabContentsView convertPoint:origin toView:nil];
+ origin = [parentWindow convertBaseToScreen:origin];
+
+ // Create the animation object to assist in animating and fading.
+ CGFloat animationHeight = MIN(bounds.height(), 4 * imageHeight);
+ NSRect frame = NSMakeRect(origin.x, origin.y, imageWidth_, animationHeight);
+ animation_ = [[AnimatableImage alloc] initWithImage:(id)image.get()
+ animationFrame:frame];
+ [parentWindow addChildWindow:animation_ ordered:NSWindowAbove];
+
+ animationHeight = MIN(bounds.height(), 3 * imageHeight);
+ [animation_ setStartFrame:CGRectMake(0, animationHeight,
+ imageWidth_, imageHeight)];
+ [animation_ setEndFrame:CGRectMake(0, imageHeight,
+ imageWidth_, imageHeight)];
+ [animation_ setStartOpacity:1.0];
+ [animation_ setEndOpacity:0.4];
+ [animation_ setDuration:0.6];
- // Must be set or else self will be leaked.
- [self setReleasedWhenClosed:YES];
+ observer_.reset(new DownloadAnimationTabObserver(self, tabContents));
// Set up to get notified about resize events on the parent window.
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
@@ -136,62 +138,12 @@ private:
selector:@selector(parentWindowChanged:)
name:NSWindowDidResizeNotification
object:parentWindow];
- [parentWindow addChildWindow:self ordered:NSWindowAbove];
-
- // Set up the root layer. By calling -setLayer: followed by -setWantsLayer:
- // the view becomes a layer hosting view as opposed to a layer backed view.
- NSView* view = [self contentView];
- CALayer* rootLayer = [CALayer layer];
- [view setLayer:rootLayer];
- [view setWantsLayer:YES];
-
- // Create the layer that will be animated.
- CALayer* layer = [CALayer layer];
- [layer setContents:(id)image.get()];
- [layer setAnchorPoint:CGPointMake(0, 1)];
- [layer setFrame:CGRectMake(0, 0, imageWidth_, imageHeight)];
- [layer setNeedsDisplayOnBoundsChange:YES];
- [rootLayer addSublayer:layer];
-
- // Common timing function for all animations.
- CAMediaTimingFunction* mediaFunction =
- [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
-
- // Positional animation.
- CABasicAnimation* positionAnimation =
- [CABasicAnimation animationWithKeyPath:@"position"];
- CGFloat animationHeight = MIN(bounds.height(), 3 * imageHeight);
- NSPoint start = NSMakePoint(0, animationHeight);
- NSPoint stop = NSMakePoint(0, imageHeight);
- [positionAnimation setFromValue:[NSValue valueWithPoint:start]];
- [positionAnimation setToValue:[NSValue valueWithPoint:stop]];
- [positionAnimation gtm_setDuration:0.6
- eventMask:NSLeftMouseUpMask];
- [positionAnimation setTimingFunction:mediaFunction];
-
- // Opacity animation.
- CABasicAnimation* opacityAnimation =
- [CABasicAnimation animationWithKeyPath:@"opacity"];
- [opacityAnimation setFromValue:[NSNumber numberWithFloat:1.0]];
- [opacityAnimation setToValue:[NSNumber numberWithFloat:0.4]];
- [opacityAnimation gtm_setDuration:0.6
- eventMask:NSLeftMouseUpMask];
- [opacityAnimation setTimingFunction:mediaFunction];
-
- // Group the animations together.
- CAAnimationGroup* animationGroup = [CAAnimationGroup animation];
- NSArray* animations =
- [NSArray arrayWithObjects:positionAnimation, opacityAnimation, nil];
- [animationGroup setAnimations:animations];
-
- // Set self as delegate so self receives -animationDidStop:finished:;
- [animationGroup setDelegate:self];
- [animationGroup setTimingFunction:mediaFunction];
- [animationGroup gtm_setDuration:0.6
- eventMask:NSLeftMouseUpMask];
- [layer addAnimation:animationGroup forKey:@"downloadOpacityAndPosition"];
-
- observer_.reset(new DownloadAnimationTabObserver(self, tabContents));
+ // When the animation window closes, it needs to be removed from the
+ // parent window.
+ [center addObserver:self
+ selector:@selector(windowWillClose:)
+ name:NSWindowWillCloseNotification
+ object:animation_];
}
return self;
}
@@ -203,28 +155,30 @@ private:
// Called when the parent window is resized.
- (void)parentWindowChanged:(NSNotification*)notification {
- NSWindow* parentWindow = [self parentWindow];
+ NSWindow* parentWindow = [animation_ parentWindow];
DCHECK([[notification object] isEqual:parentWindow]);
NSRect parentFrame = [parentWindow frame];
NSRect frame = parentFrame;
frame.size.width = MIN(imageWidth_, NSWidth(parentFrame));
- [self setFrame:frame display:YES];
+ [animation_ setFrame:frame display:YES];
}
-// CAAnimation delegate method called when the animation is complete.
-- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag {
+- (void)windowWillClose:(NSNotification*)notification {
+ DCHECK([[notification object] isEqual:animation_]);
[self animationComplete];
}
-// Common clean up code.
- (void)animationComplete {
- [[self parentWindow] removeChildWindow:self];
- [self close];
+ [[animation_ parentWindow] removeChildWindow:animation_];
+ [self release];
}
+ (void)startAnimationWithTabContents:(TabContents*)contents {
// Will be deleted when the animation is complete in -animationComplete.
- [[self alloc] initWithTabContents:contents];
+ DownloadStartedAnimationMac* controller =
+ [[self alloc] initWithTabContents:contents];
+ // The |animation_| releaes itself when done.
+ [controller->animation_ startAnimation];
}
@end

Powered by Google App Engine
This is Rietveld 408576698