- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / download / download_started_animation_mac.mm
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // This file contains the Mac implementation the download animation, displayed
6 // at the start of a download. The animation produces an arrow pointing
7 // downwards and animates towards the bottom of the window where the new
8 // download appears in the download shelf.
9
10 #include "chrome/browser/download/download_started_animation.h"
11
12 #import <QuartzCore/QuartzCore.h>
13
14 #include "base/logging.h"
15 #import "chrome/browser/ui/cocoa/animatable_image.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/browser/web_contents_view.h"
18 #include "grit/theme_resources.h"
19 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
20 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/gfx/image/image.h"
23 #include "ui/gfx/rect.h"
24
25 class DownloadAnimationWebObserver;
26
27 // A class for managing the Core Animation download animation.
28 // Should be instantiated using +startAnimationWithWebContents:.
29 @interface DownloadStartedAnimationMac : NSObject {
30  @private
31   CGFloat imageWidth_;
32   AnimatableImage* animation_;
33 };
34
35 + (void)startAnimationWithWebContents:(content::WebContents*)webContents;
36
37 @end
38
39 @implementation DownloadStartedAnimationMac
40
41 - (id)initWithWebContents:(content::WebContents*)webContents {
42   if ((self = [super init])) {
43     // Load the image of the download arrow.
44     ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
45     NSImage* image =
46         bundle.GetNativeImageNamed(IDR_DOWNLOAD_ANIMATION_BEGIN).ToNSImage();
47
48     // Figure out the positioning in the current tab. Try to position the layer
49     // against the left edge, and three times the download image's height from
50     // the bottom of the tab, assuming there is enough room. If there isn't
51     // enough, don't show the animation and let the shelf speak for itself.
52     gfx::Rect bounds;
53     webContents->GetView()->GetContainerBounds(&bounds);
54     imageWidth_ = [image size].width;
55     CGFloat imageHeight = [image size].height;
56
57     // Sanity check the size in case there's no room to display the animation.
58     if (bounds.height() < imageHeight) {
59       [self release];
60       return nil;
61     }
62
63     NSView* tabContentsView = webContents->GetView()->GetNativeView();
64     NSWindow* parentWindow = [tabContentsView window];
65     if (!parentWindow) {
66       // The tab is no longer frontmost.
67       [self release];
68       return nil;
69     }
70
71     NSPoint origin = [tabContentsView frame].origin;
72     origin = [tabContentsView convertPoint:origin toView:nil];
73     origin = [parentWindow convertBaseToScreen:origin];
74
75     // Create the animation object to assist in animating and fading.
76     CGFloat animationHeight = MIN(bounds.height(), 4 * imageHeight);
77     NSRect frame = NSMakeRect(origin.x, origin.y, imageWidth_, animationHeight);
78     animation_ = [[AnimatableImage alloc] initWithImage:image
79                                          animationFrame:frame];
80     [parentWindow addChildWindow:animation_ ordered:NSWindowAbove];
81
82     animationHeight = MIN(bounds.height(), 3 * imageHeight);
83     [animation_ setStartFrame:CGRectMake(0, animationHeight,
84                                          imageWidth_, imageHeight)];
85     [animation_ setEndFrame:CGRectMake(0, imageHeight,
86                                        imageWidth_, imageHeight)];
87     [animation_ setStartOpacity:1.0];
88     [animation_ setEndOpacity:0.4];
89     [animation_ setDuration:0.6];
90
91     // Set up to get notified about resize events on the parent window.
92     NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
93     [center addObserver:self
94                selector:@selector(parentWindowDidResize:)
95                    name:NSWindowDidResizeNotification
96                  object:parentWindow];
97     // When the animation window closes, it needs to be removed from the
98     // parent window.
99     [center addObserver:self
100                selector:@selector(windowWillClose:)
101                    name:NSWindowWillCloseNotification
102                  object:animation_];
103     // If the parent window closes, shut everything down too.
104     [center addObserver:self
105                selector:@selector(windowWillClose:)
106                    name:NSWindowWillCloseNotification
107                  object:parentWindow];
108   }
109   return self;
110 }
111
112 - (void)dealloc {
113   [[NSNotificationCenter defaultCenter] removeObserver:self];
114   [super dealloc];
115 }
116
117 // Called when the parent window is resized.
118 - (void)parentWindowDidResize:(NSNotification*)notification {
119   NSWindow* parentWindow = [animation_ parentWindow];
120   DCHECK([[notification object] isEqual:parentWindow]);
121   NSRect parentFrame = [parentWindow frame];
122   NSRect frame = parentFrame;
123   frame.size.width = MIN(imageWidth_, NSWidth(parentFrame));
124   [animation_ setFrame:frame display:YES];
125 }
126
127 // When the animation closes, release self.
128 - (void)windowWillClose:(NSNotification*)notification {
129   [[animation_ parentWindow] removeChildWindow:animation_];
130   [self release];
131 }
132
133 + (void)startAnimationWithWebContents:(content::WebContents*)contents {
134   // Will be deleted when the animation window closes.
135   DownloadStartedAnimationMac* controller =
136       [[self alloc] initWithWebContents:contents];
137   // The initializer can return nil.
138   if (!controller)
139     return;
140
141   // The |controller| releases itself when done.
142   [controller->animation_ startAnimation];
143 }
144
145 @end
146
147 void DownloadStartedAnimation::Show(content::WebContents* web_contents) {
148   DCHECK(web_contents);
149
150   // Will be deleted when the animation is complete.
151   [DownloadStartedAnimationMac startAnimationWithWebContents:web_contents];
152 }