Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / animatable_view.mm
blobcb00e047fb2b493f8e054e8f88db3117497f834b
1 // Copyright (c) 2009 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.
5 #import <Cocoa/Cocoa.h>
6 #import <QuartzCore/QuartzCore.h>
8 #import "chrome/browser/ui/cocoa/animatable_view.h"
9 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h"
11 // NSAnimation subclass that animates the height of an AnimatableView.  Allows
12 // the caller to start and cancel the animation as desired.
13 @interface HeightAnimation : NSAnimation {
14  @private
15   AnimatableView* view_;  // weak, owns us.
16   CGFloat startHeight_;
17   CGFloat endHeight_;
20 // Initialize a new height animation for the given view.  The animation will not
21 // start until startAnimation: is called.
22 - (id)initWithView:(AnimatableView*)view
23        finalHeight:(CGFloat)height
24           duration:(NSTimeInterval)duration;
25 @end
27 @implementation HeightAnimation
28 - (id)initWithView:(AnimatableView*)view
29        finalHeight:(CGFloat)height
30           duration:(NSTimeInterval)duration {
31   if ((self = [super gtm_initWithDuration:duration
32                                 eventMask:NSLeftMouseUpMask
33                            animationCurve:NSAnimationEaseIn])) {
34     view_ = view;
35     startHeight_ = [view_ height];
36     endHeight_ = height;
37     [self setAnimationBlockingMode:NSAnimationNonblocking];
38     [self setDelegate:view_];
39   }
40   return self;
43 // Overridden to call setHeight for each progress tick.
44 - (void)setCurrentProgress:(NSAnimationProgress)progress {
45   [super setCurrentProgress:progress];
46   [view_ setHeight:((progress * (endHeight_ - startHeight_)) + startHeight_)];
48 @end
51 @implementation AnimatableView
52 @synthesize delegate = delegate_;
53 @synthesize resizeDelegate = resizeDelegate_;
55 - (void)dealloc {
56   // Stop the animation if it is running, since it holds a pointer to this view.
57   [self stopAnimation];
58   [super dealloc];
61 - (CGFloat)height {
62   return [self frame].size.height;
65 - (void)setHeight:(CGFloat)newHeight {
66   // Force the height to be an integer because some animations look terrible
67   // with non-integer intermediate heights.  We only ever set integer heights
68   // for our views, so this shouldn't be a limitation in practice.
69   int height = floor(newHeight);
70   [resizeDelegate_ resizeView:self newHeight:height];
73 - (void)animateToNewHeight:(CGFloat)newHeight
74                   duration:(NSTimeInterval)duration {
75   [currentAnimation_ stopAnimation];
77   currentAnimation_.reset([[HeightAnimation alloc] initWithView:self
78                                                     finalHeight:newHeight
79                                                        duration:duration]);
80   if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
81     [resizeDelegate_ setAnimationInProgress:YES];
82   [currentAnimation_ startAnimation];
85 - (void)stopAnimation {
86   [currentAnimation_ stopAnimation];
89 - (NSAnimationProgress)currentAnimationProgress {
90   return [currentAnimation_ currentProgress];
93 - (void)animationDidStop:(NSAnimation*)animation {
94   if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
95     [resizeDelegate_ setAnimationInProgress:NO];
96   if ([delegate_ respondsToSelector:@selector(animationDidStop:)])
97     [delegate_ animationDidStop:animation];
98   currentAnimation_.reset(nil);
101 - (void)animationDidEnd:(NSAnimation*)animation {
102   if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
103     [resizeDelegate_ setAnimationInProgress:NO];
104   if ([delegate_ respondsToSelector:@selector(animationDidEnd:)])
105     [delegate_ animationDidEnd:animation];
106   currentAnimation_.reset(nil);
109 @end