Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / ios / chrome / browser / ui / animation_util.mm
blob1878c3e7709240f1422a4bf076c56ab74db7e329
1 // Copyright 2014 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 #include "ios/chrome/browser/ui/animation_util.h"
7 #include <algorithm>
8 #include <cmath>
10 #include "ios/chrome/browser/ui/reversed_animation.h"
12 CAAnimation* FrameAnimationMake(CALayer* layer,
13                                 CGRect beginFrame,
14                                 CGRect endFrame) {
15   CGRect beginBounds = {CGPointZero, beginFrame.size};
16   CGRect endBounds = {CGPointZero, endFrame.size};
17   CABasicAnimation* boundsAnimation =
18       [CABasicAnimation animationWithKeyPath:@"bounds"];
19   boundsAnimation.fromValue = [NSValue valueWithCGRect:beginBounds];
20   boundsAnimation.toValue = [NSValue valueWithCGRect:endBounds];
21   boundsAnimation.removedOnCompletion = NO;
22   boundsAnimation.fillMode = kCAFillModeBoth;
23   CGPoint beginPosition = CGPointMake(
24       beginFrame.origin.x + layer.anchorPoint.x * beginBounds.size.width,
25       beginFrame.origin.y + layer.anchorPoint.y * beginBounds.size.height);
26   CGPoint endPosition = CGPointMake(
27       endFrame.origin.x + layer.anchorPoint.x * endBounds.size.width,
28       endFrame.origin.y + layer.anchorPoint.y * endBounds.size.height);
29   CABasicAnimation* positionAnimation =
30       [CABasicAnimation animationWithKeyPath:@"position"];
31   positionAnimation.fromValue = [NSValue valueWithCGPoint:beginPosition];
32   positionAnimation.toValue = [NSValue valueWithCGPoint:endPosition];
33   positionAnimation.removedOnCompletion = NO;
34   positionAnimation.fillMode = kCAFillModeBoth;
35   return AnimationGroupMake(@[ boundsAnimation, positionAnimation ]);
38 CAAnimation* OpacityAnimationMake(CGFloat beginOpacity, CGFloat endOpacity) {
39   CABasicAnimation* opacityAnimation =
40       [CABasicAnimation animationWithKeyPath:@"opacity"];
41   opacityAnimation.fromValue = @(beginOpacity);
42   opacityAnimation.toValue = @(endOpacity);
43   opacityAnimation.fillMode = kCAFillModeBoth;
44   opacityAnimation.removedOnCompletion = NO;
45   return opacityAnimation;
48 CAAnimation* AnimationGroupMake(NSArray* animations) {
49   CAAnimationGroup* animationGroup = [CAAnimationGroup animation];
50   animationGroup.animations = animations;
51   CFTimeInterval duration = 0.0;
52   for (CAAnimation* animation in animations)
53     duration = std::max(duration, animation.beginTime + animation.duration);
54   animationGroup.duration = duration;
55   animationGroup.fillMode = kCAFillModeBoth;
56   animationGroup.removedOnCompletion = NO;
57   return animationGroup;
60 CAAnimation* DelayedAnimationMake(CAAnimation* animation,
61                                   CFTimeInterval delay) {
62   CAAnimation* delayedAnimation = [[animation copy] autorelease];
63   if (delayedAnimation) {
64     delayedAnimation.beginTime = delay;
65     delayedAnimation = AnimationGroupMake(@[ delayedAnimation ]);
66   }
67   return delayedAnimation;
70 CABasicAnimation* FindAnimationForKeyPath(NSString* keyPath,
71                                           CAAnimation* animation) {
72   __block CABasicAnimation* animationForKeyPath = nil;
73   if ([animation isKindOfClass:[CABasicAnimation class]]) {
74     CABasicAnimation* basicAnimation =
75         static_cast<CABasicAnimation*>(animation);
76     if ([basicAnimation.keyPath isEqualToString:keyPath])
77       animationForKeyPath = basicAnimation;
78   } else if ([animation isKindOfClass:[CAAnimationGroup class]]) {
79     CAAnimationGroup* animationGroup =
80         static_cast<CAAnimationGroup*>(animation);
81     [animationGroup.animations
82         enumerateObjectsUsingBlock:^(CAAnimation* subAnimation, NSUInteger idx,
83                                      BOOL* stop) {
84           animationForKeyPath = FindAnimationForKeyPath(keyPath, subAnimation);
85           *stop = animationForKeyPath != nil;
86         }];
87   }
88   return animationForKeyPath;
91 void RemoveAnimationForKeyFromLayers(NSString* key, NSArray* layers) {
92   for (CALayer* layer in layers)
93     [layer removeAnimationForKey:key];